<?php
/**
 ************************************************************************************
 * Dream  PHP开发框架    整个框架仅此一个文件   无其他任何附加代码   
 *-----------------------------------------------------------------------------------
 * 版权所有: CopyRight By 8000km.com
 * 您可以自由使用该源码，请保留作者信息。尊重他人劳动成果就是尊重自己
 *-----------------------------------------------------------------------------------
 * Author:武恒  Dtime:2015-07-8  QQ 339300767  个人网址 8000km .cn
 *-----------------------------------------------------------------------------------
 * 使用技巧：导入此文件并new Dream类。举个栗子 include('dream.php');  new Dream(); 
**************************************************************************************
*/
header("Content-type: text/html; charset=utf-8"); 
/**
 * 取数组维数
 * @param  array $arr  
 * @return int
 */
function getMaxArr($arr) {
    if (!is_array($arr)) {
        return 0;
    } else {
        $dimension = 0;
        foreach ($arr as $item) {
            $t = getMaxArr($item);
            if ($t > $dimension) {
                $dimension = $t;
            }
        }
        return $dimension +1;
    }
}
/**
 * 打印数据，截断程序。
 * @param mixed $v 
 */
function dump($v = 'ok') {
    echo '<pre>';
    var_dump($v);
    echo '</pre>';
    stop();
}
/**
 * 删除目录和文件。
 * @param  string $delPath 文件目录
 * @return bool
 */
function delDir($delPath, $redir = true) {			
    if (is_dir($delPath)) {					    		
            $filesRes    =  opendir($delPath);				
            while (($file = readdir($filesRes)) !== false) {	
                    if ($file != "."&&$file != "..") {			
                        if (is_file($delPath."/".$file)) {      	
                            unlink($delPath."/".$file);		
                        } else {
                            delDir($delPath."/".$file);
                        }
                    }
            }
            closedir($filesRes);
            if ($redir == true) {
                return rmdir($delPath);
            }
    } else if (is_file($delPath)) {
        return unlink($delPath);						
    } else {
            return false;
    }
}
/**
 *取文件后缀
 *@param string $file 
 *@return string
 */
function getExt($file) { 
    return pathinfo($file, PATHINFO_EXTENSION); 
}

/**
 * 生成随机字符串
 * @param int $length 生成字符串的长度
 * @return string 
 */
function getRandChar($length) {
   $str     = null;
   $strPol  = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
   $max     = strlen($strPol)-1;
   for ( $i = 0; $i < $length; $i++ ) {
        $str .= $strPol[rand(0,$max)];
   }
   return $str;
}
/**
 * 终止程序
 */
function stop($i = 0){
    exit($i);
}
/**
 * 取时间
 */
function getTime($date = null){
    return (empty($date)) ? date('Y-m-d H:i:s') : time();
}
/**
 * 框架参数初始化类
 * 主要用于初始化整个框架使用的参数
 * @author 武恒 <8000km.cn>
 */
class Base
{   
    /**
     * 初始化构造
     */
    public function  __construct($appPath) {       
        // 框架基础配置文件
        preg_match('@.*(\.php)?@',$_SERVER['SCRIPT_NAME'], $res); 
        //index文件相对于web目录的相对路径
	if (empty($res[0])) {
		$webUrl  = '/'; 
	} else {
        $webUrl  = substr($res[0],0,strripos($res[0],'/')+1);
	}
        //index文件绝对路径
        $webRoot = $_SERVER['DOCUMENT_ROOT'].$webUrl;

        $isTrue  = false; 
        $appPaths= array();            
        $appPath = (array) $appPath;
        //以下两个判断用于处理主应用目录的点和斜线数组操作字符串
        if ($appPath[0][0] == '.' && $appPath[0][1] != '.') {
            $appPath[0] = trim($appPath[0], '.');
        }
        if ($appPath[0][0] == '/'){
            $appPath[0] = trim($appPath[0], '/');
        }
        //此处判断主要用于初始化站点二级应用
        if (is_file($webRoot.$appPath[0].'/Config/config.php') && isset($appPath[1])) {
            include($webRoot.$appPath[0].'/Config/config.php');
            $isTrue = isset($appPaths[$appPath[1]]);
        } 
        if ($isTrue) {
            define('SIGN', $appPaths[$appPath[1]]);
        } elseif (!defined('SIGN')){  
            define('SIGN', $appPath[0]);
        } 
		//此处常量对于二级域名极为重要 不能修改和移动位置	
        $app     = SIGN;    
        $rap     = $webRoot.$app.'/';                   
        $webIp   = isset($_SERVER['SERVER_ADDR'])?$_SERVER['SERVER_ADDR']:$_SERVER["LOCAL_ADDR"];
		if (substr($_SERVER["REQUEST_URI"], 0, strlen($_SERVER["SCRIPT_NAME"]))==$_SERVER["SCRIPT_NAME"]) {
			$isRewrite = false;
		} else {
			$isRewrite = true;	
		}	
        $webPath   = array(
            'WebName'       => $_SERVER['HTTP_HOST'],                       //网站域名
            'WebUrl'        => $webUrl,                                     //网站相对路径
            'WebRoot'       => $webRoot,                                    //网站绝对路径
            'App'           => $app,                                        //应用名
            'INDEX'         => 'http://'.$_SERVER['HTTP_HOST'].$webUrl,     //主页地址
            //以下为绝对目录
            'Plug'          => $rap.'Plug/',                                //插件目录
            'Public'        => $webRoot.'Public/',                                //资源目录
            'Config'        => $rap.'Config/',                              //用户配置文件目录
            'Controller'    => $rap.'Home/Controller/',                     //控制层目录
            'View'          => $rap.'Home/View/',                           //是涂层目录
            'LayoutPath'    => $rap.'Home/View/Layout/',                    //布局目录
            'Data'          => $rap.'RunTime/Data/',                        //数据总缓存目录
            'ClassData'     => $rap.'RunTime/Data/ClassData/',              //php文件缓存目录
            'AppCache'      => $rap.'RunTime/Data/AppData/',                //数据缓存目录
            'Logs'          => $rap.'RunTime/Logs/',                        //日志目录
            'Temp'          => $rap.'RunTime/Temp/',                        //静态页缓存目录
            'RunTime'       => $rap.'RunTime/',                             //缓存总文件夹
            'RootApp'       => $rap,                                        //应用绝对路径
            '_InfoTpl_'     => $rap.'Home/View/InfoTpl/',                   //信息提示模版目录
            'pic'           => array('ico','jpg','png','bmp','gif','pdf'),  //框架自用
            '__PUBLIC__'    => $webUrl.'Public',                            //资源文件夹
			'isRewrite'     => $isRewrite                                   //当前访问是否伪静态
        );

        $webConfig = array(
			'newWebON'      => true,                                            //网站初始化开关
            'version'       => '3.2.2',                                         //版本号
            'CheckSql'      => '/(union|sleep|benchmark|load_file|outfile)/i',  //需要屏蔽的sql函数
            'Timezone'      => 'PRC',                                           //时区
            'TplExt'        => 'html',                                          //模版后缀
            'TplL'          => '<{',                                            //左标示符
            'Suffix'        => 'shtml',                                         //伪静态后缀
            'TplR'          => '}>',                                            //右标示符
            'WriteLog'      => true,                                            //日志开关
            'CloseWarning'  => false,                                           //php引擎提示开关
            'CloseError'    => false,                                           //输出错误开关
            'LogLevel'      => 4,                                               //日志筛选等级
            'SQLslow'       => true,                                            //数据库慢查询开关
            'SQLtime'       => 2,                                               //数据库慢查询捕获时间
            'WebIp'         => $webIp,                                          //网站ip
            'Cache'         => true,                                            //缓存开关
            'Mobile'        => true,                                            //启用手机模版开关
            'Token'         => 'I love you my Dream',                           //默认加密子串
            'Layout'        => false,                                           //模版布局标签  不可更改
            'LayoutName'    => 'layout',                                        //默认布局文件名
            'LayoutContent' => 'content',                                       //默认布局内容名
            'InputCheck'    => 3,                                               //输入检查开关
            'ZipCode'       => true,                                            //代码压缩开关
            'MakeHtml'      => false,                                           //静态检查标识  不可更改
            'Expire'        => 3600,                                            //文件缓存默认时间
            'AppDataCatalog'=> 'Temp',                                          //文件缓存默认分组
            'AppCacheSize'  => 1,                                               //文件缓存默认深度
            'HtmlCacheTime' => 0,                                               //静态页面缓存时间 0为永不失效
            'WebOff'        => false,                                           //网站开关
            'Rewrite'       => false                                            //伪静态开关
        );
        foreach ($webPath as $k => $v) {
            $this ->$k = $v;
        }

        //驱动用户配置
        $userDefined  = $config = array();
        $dbConfig     = ''; 
        if (is_file($this->Config.'config.php')) { 
            require($this->Config.'config.php');   
            $webConfig = array_merge($webConfig, $config); 
            $this-> userDefined = $userDefined;
            $this-> dbConfig    = $dbConfig;
			$this-> rewriteRule = $rewriteRule;
        }
        foreach ($webConfig as $k => $v) {
            $this->$k = $v;
        }
        date_default_timezone_set($this->Timezone);
    }
	/**
	 * 跨级导入参数
	 */
    final protected function relay() {
        foreach (func_get_arg(0) as $k => $v) {
            $this ->$k = $v;
        }
    }
    /**
     * 框架日志写入程序，将指定内容写入框架日志
     * @param string $content	内容
     * @param int $level	等级
     * @return void
     */
    final protected function writeLog( $content = '', $level = 4) {	
        if ($this->LogLevel < $level) {
            return false;
        }
        $content = empty($content) ? '调用了日志写入，但没有传入内容' : $content;
        $file    = $this->Logs.Date('Y').'/'.Date('m').'/'.SIGN.'Logs'.Date('Y-m-d').'.txt';
        if (!is_file($file)) {
            new MakeFile($file);
        }
        if (is_writable($file)) {    
            $LogFile = fopen($file,'a'); 	            
            $text    = date("Y-m-d H:i:s")."\t".$content."。\r\n";								
            $res     = fwrite($LogFile, $text);		
            fclose($LogFile);
        }
		return $res;
    }
    /**
     * 得到HASE名
     * @param string $name
     * @return string
     */
    protected function getHASEname($name, $flag = false) { 
        $key = '';
        if ($flag) {
            $flag = $_POST;
        } else {
            $flag = $_GET;
        }
        foreach ($flag as $v => $k) {
            $key .= $v.$name.$k;
        }
        return(md5($key));
    }
    /**
     * 强行跳转
     */
    protected function setStatus($code = 301, $address = null) { 
        if (empty($address)) {
            $address = $this->INDEX;
        }
        switch($code){
            case 301:
                Header("HTTP/1.1 301 Moved Permanently");
                Header("Location:".$address );
                break;
            case 404:
                Header("HTTP/1.1 404 Not Found");
                break;
            case 403:
                Header("HTTP/1.1 403 Forbidden");
                break;
            default:
                Header("HTTP/1.1 301 Moved Permanently");
                Header("Location:".$address );
                break;
        }
    }
    /**
     * 判断是否是移动设备
     */
    protected function isMobile() { 
		if (!$this->Mobile) {
			return false;
		}
        if (isset ($_SERVER['HTTP_X_WAP_PROFILE'])){
            return true;
        }
        if (isset ($_SERVER['HTTP_VIA'])){
            return stristr($_SERVER['HTTP_VIA'], "wap") ? true : false;
        }
        if (isset ($_SERVER['HTTP_USER_AGENT']))
        {
            $clientkeywords = array (
                'sony',     'ericsson',       'mot',   'samsung',     'htc',       'sgh',     'lg',       'sharp', 
                'sie-',      'philips', 'panasonic',   'alcatel',  'lenovo',    'iphone',   'ipod',  'blackberry',
                'meizu',     'android',  'netfront',   'symbian',   'ucweb', 'windowsce',   'palm',   'operamini',
                'operamobi','openwave',  'nexusone',      'cldc',    'midp',       'wap', 'mobile',       'nokia',
            ); 
            foreach ($clientkeywords as $v) {
                if (strpos(strtolower($_SERVER['HTTP_USER_AGENT']),$v) !== false) {
                    return true;
                }
            }
        } 
        return false;
    }
}
/**
 * 框架引导类，网站入口第一步
 * @author 武恒 <www.8000km.cn>
 * @param string 应用目录
 */
class Dream extends Base
{	
    /**
     * 网站初始化框架
     */
    public function __construct($start = 'Application') {  
        try{ 
            if (version_compare("5.2", PHP_VERSION, ">")) {
                throw new Exception("需要 php5.2 或以上的版本支持！",101);
            }
            //此处为解析二级域名，如解析到二级则初始化 www与空 解析为false 走Application 
            if (($host = Route::getHost()) !== false) {
                $appPath = array($start,$host);
            } else {
                $appPath = array($start);
            }
            parent::__construct($appPath);
            //执行自定义初始化
            if (is_file($this->Config.'Hook.class.php')) {
                include_once($this->Config.'Hook.class.php');
                $this->hook = new Hook;
                $this->hook -> init();
            }	
            if ($this->CloseWarning == true) {
               ini_set('display_errors', false);
               error_reporting(0);
            } else {
               ini_set('display_errors', true); 
               error_reporting(E_ALL);  
            }    
            if (!is_dir($this->RootApp)) {  
                $this->newWeb();
            } else {   
            //初始化路由
                $obj = new Route(get_object_vars($this));
                if (($info = $obj -> getRoute()) != false) { 
                    $this->play($info);
                } else {
                    $this->newWeb();
                }
            }
            //执行结尾函数
            if (isset($this->hook)) { 
                $this->hook->end();   
            }
            //框架错误捕获处理入口
        } catch(Exception $e) {
            if ($e-> getCode() == 101) {
                echo $e-> getMessage();
            } else {
                new E($e-> getMessage(),$e-> getCode());
            }
        }
    }
    /**
     * 初始化新网站
     */
    private function newWeb() {
		if (!isset($this->newWebON) || !$this->newWebON) {
			throw new Exception("配置错误！",101);
		}	
        //新网站随机密钥
        $webToKen = getRandChar(10);
        //锁模版
        $Colck    = 'Dream框架初始化锁定检查文件，尽可能不要删除。以防造成损失。';
        //信息提示窗模版
        $info     = <<<EF
<{__NOLAYOUT__}>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd">
<HTML xmlns="http://www.w3.org/1999/xhtml">
<HEAD><TITLE><{\$msg['title']}></TITLE>
<META content="text/html; charset=utf-8" http-equiv=Content-Type>
<STYLE type="text/css">
A {COLOR: #003366; TEXT-DECORATION: none}
A:hover {TEXT-DECORATION: underline}
TABLE {FONT: 9pt Tahoma, Verdana; COLOR: #000000;margin-top:200px;}
.header {BACKGROUND-COLOR: #add2da; FONT: bold 9pt Tahoma, Verdana; COLOR: #ffffff}
.tableborder {BORDER-BOTTOM: #8cbdef 1px solid; BORDER-LEFT: #8cbdef 1px solid; BACKGROUND: #cde2f8; BORDER-TOP: #8cbdef 1px solid; BORDER-RIGHT: #8cbdef 1px solid}
</STYLE>
<script>
    var t = <{\$msg['t']}>; 
function countDown() { 
    var time = document.getElementById("time"); 
    t--; 
    time.innerHTML = t; 
    if ( t == 1 ) { 
        location.href = '<{\$msg["url"]}>'; 
        clearInterval(inter); 
    } 
}
function begin() {   
    if (t < 999) {
        var inter = setInterval("countDown()", 1000); 
    } else {  
        document.getElementById("info").innerHTML = "";
    }
}
window.onload=begin;
</script>
</HEAD>
<BODY><BR><BR><BR><BR><BR><BR>
<TABLE class=tableborder border=0 cellSpacing=1 cellPadding=3 width=500 align=center>
<TBODY>
    <TR class=header>
        <TD height=25><DIV align=center><{\$msg['title']}></DIV></TD>
    </TR>
  	<TR bgColor=#ffffff>
    	<TD height=80>
     	<DIV align="center" style="color:#333">
        	<BR><B><{\$msg['info']}></B><BR><BR>
            <span id="info"><span id="time"><{\$msg['t']}></span>秒后自动跳转，如没有跳转功能请点<A href="<{\$msg['url']}>">直接跳转</A>&nbsp; <BR><BR></span>
  	</DIV>
  	</TD>
   </TR>
</TBODY>
</TABLE>
</BODY>
</HTML>
EF;
	//初始化路径模版
	$Tpl = array(
            'index.html',
            'Plug/index.html',
            'Config/index.html',
            'Home/index.html',
            'Home/Controller/index.html',														
            'Home/Controller/Index/index.html',							
            'Home/View/index.html',					
            'Home/View/InfoTpl/index.html',										
            'RunTime/index.html',									
            'RunTime/Data/index.html',				
            'RunTime/Logs/index.html',				
            'RunTime/Temp/index.html'				
	);
	//文件夹授权
	$chmod = array(
            'Config/'   		    => 507,
            'Home/'                 => 507,
            'Home/Controller/'      => 507,														
            'Home/Controller/Index/'=> 507,							
            'Home/View/'            => 507,					
            'Home/View/InfoTpl/'    => 507,										
            'RunTime/'              => 707,									
            'RunTime/Data/'         => 707,				
            'RunTime/Logs/'         => 707,				
            'RunTime/Temp/'         => 707				
	);
	//配置文件内容模版
	$config = <<<EF
<?php
//用户自定义数组  可在前后台调用
\$userDefined = array(
    //'__GVAR__' => \$_GET
);
//用户 配置 数组  需要配置项 去掉注释符
\$config = array(
	'newWebON'          => false,                                         //网站初始化开关
	'Token'             => '$webToKen',                                   //加密密钥
	//'CheckSql'        => '/(union|sleep|benchmark|load_file|outfile)/i',//需要屏蔽的sql函数 正则表达式
	//'Timezone'        => 'PRC',                                         //时区
	//'TplExt'          => 'html',                                        //模版后缀
    //'Suffix'          => 'html',                                        //伪静态后缀
	//'TplL'            => '<{',                                          //左标示符
	//'TplR'            => '}>',                                          //右标示符
	//'WriteLog'        => true,                                          //日志开关
	//'CloseWarning'    => false,                                         //php引擎提示开关
	//'CloseError'      => false,                                         //输出错误开关
	//'LogLevel'        => 4,                                             //日志筛选等级
	//'SQLslow'         => true,                                          //数据库慢查询开关
	//'SQLtime'         => 2,                                             //数据库慢查询捕获时间
	//'Cache'           => true,                                          //缓存开关
	//'Mobile'          => true,                                          //启用手机模版开关
	//'LayoutName'      => 'layout',                                      //默认布局文件名
	//'LayoutContent'   => 'content',                                     //默认布局内容名
	//'InputCheck'      => 1,                                             //输入检查开关
	//'ZipCode'         => true,                                          //代码压缩开关
	//'Expire'          => 3600,                                          //文件缓存默认时间
	//'AppDataCatalog'  => 'Temp',                                        //文件缓存默认分组
	//'AppCacheSize'    => 1,                                             //文件缓存默认深度
	//'HtmlCacheTime'   => 0,                                             //静态页面缓存时间 0为永不失效
    //'WebOff'          => '网站正在升级维护请稍候访问，开启时间待定。',  //网站开关
    //'Rewrite'         => false,                                         //伪静态开关
);
//数据库配置 可配置多库 多用户登录和使用  
\$dbConfig = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
    <obj>
        <dream_root>                        
            <name>mydream</name>            
            <dataType>mysqli</dataType>     
            <tablePrefix>dr_</tablePrefix>    
            <dataUrl>127.0.0.1</dataUrl>    
            <dataUser>root</dataUser>       
            <dataPwd>123456</dataPwd>       
            <char>utf8</char>               
            <port>3306</port>               
        </dream_root>
		
        <dream_test>
            <name>phpmodel</name>
            <dataType>mysqli</dataType>
            <tablePrefix>pm_</tablePrefix>
            <dataUrl>127.0.0.1</dataUrl>
            <dataUser>test</dataUser>
            <dataPwd>123456</dataPwd>
            <char>utf8</char>
            <port>3306</port>
        </dream_test>
    </obj>
XML;

//用户二级域名定义池
\$appPaths = array(
    //这里定义的键名是URL二级域名，键值是应用目录
    //'bbs'=>'bbs'
);

//伪静态规则
\$rewriteRule = array(
	//这里定义的键名url是伪静态 值是替换的正则内容  
	//举个栗子 http://localhost/xinwen22 =>  http://localhost/inddex.php?ap=index&op=index&p=22
	//其中index.php 在服务器端隐藏
	//'xinwen(\d+)?' => 'ap=index&op=index&p=$1',
	//'xinwen' => 'ap=index&op=index'
);

EF;
        //用户公共函数模版
        $common = <<<EF
<?php
/**
 * 无限排序函数
 * @param  array  \$items		需要排序的数组
 * @param  array  \$id  		需要排序的主键默认id
 * @param  array  \$pid  		需要排序的外键默认pid
 * @param  array  \$son  		排序后的子健标识
 * @return array
 */
function genTree(\$items,\$id='id',\$pid='pid',\$son = 'children') {
    \$tree = array(); 				
    \$tmpMap = array();  			    
    foreach (\$items as \$item) {
        \$tmpMap[\$item[\$id]] = \$item;		
    }										 
    foreach (\$items as \$item) {			
        if (isset(\$tmpMap[\$item[\$pid]])) {			
            \$tmpMap[\$item[\$pid]][\$son][] = &\$tmpMap[\$item[\$id]];
        } else {													
            \$tree[] = &\$tmpMap[\$item[\$id]];							
        }
    }
    unset(\$tmpMap);
    return \$tree;
}

EF;
        //类模版
        $index = <<<EF
<?php
class IndexAction extends Action 
{
    function index()
    {
        echo '欢迎使用Dream 框架，祝您工作好心情！<br /><br />当前版本 '.\$this->version;
    }
}

EF;
        //插件模版
        $hook = <<<EF
<?php
class Hook  extends Action
{
    public function init() {
        //框架初始化会加载此函数，此处不能对库操作
        return;
    }
    public function begin() {
        //类初始化会加载此函数，此处及以下可以对库操作
        return;
    }
    public function end() {
        //框架结束会加载此函数
        return;
    }
}   

EF;
        //预执行模版
        $preExe = <<<EF
<?php
class PreExe  extends Action
{
    public function func ()
    {
        // 类初始化前加载函数
    }
}

EF;
        //apache.htaccess文件
        $hts = <<<EF
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
</IfModule>        
EF;
        $Fil = array(
            $info	=> 'Home/View/InfoTpl/info.html',
            $Colck  => 'Home/Controller/clock',
            $config => 'Config/config.php',
            $common	=> 'Config/common.php',
            $index	=> 'Home/Controller/Index/IndexAction.class.php',
            $preExe => 'Home/Controller/Index/PreExe.class.php',
            $hook   => 'Config/Hook.class.php',
            $hts    => '.htaccess'
         );
        $mak = new MakeFile();
        foreach ($Tpl as $v) {
            if ($mak ->fil($this->WebRoot.$this->App.'/'.$v) === false) {
                throw new Exception('文件夹初始化失败-'.$mak->info, 101);
            }
        }
        foreach ($Fil as $k => $v) {
            if ($mak ->fil($this->WebRoot.$this->App.'/'.$v,$k) === false) {
                throw new Exception('文件初始化失败-'.$mak->info, 101);
            }
        }
        //文件夹授权
        if (function_exists('posix_getuid') && function_exists('stat')) {
            $pid = posix_getuid();
            foreach ($chmod as $k => $v) {
                if (is_dir($this->WebRoot.$this->App.'/'.$k)) {
                    $fileId = stat($this->WebRoot.$this->App.'/'.$k);
                    if ($pid == $fileId['uid']) {   
                        chmod($this->WebRoot.$this->App.'/'.$k,$v);
                    }
                }
            }
        }
        $arrInfo = array();
        $arrInfo['ap'] = 'Index';
        $arrInfo['op'] = 'index';
        $this->play($arrInfo);
    }
    /**
     * 完成各种检查，移权并初始化用户自定义类和方法。
     */ 
    private function play($get) {   
        if (!is_array($get)) {
            throw new Exception('空参',505);
        }
        if (empty($get['ap'])) {
            $get['ap'] = 'Index';
        }
        if (empty($get['op'])) {
            $get['op'] = 'index';
        } 
		$_GET = array_merge($_GET, $get);
        $get['ap']= ucwords(strtolower($get['ap']));
        if (!is_file($this->Controller.$get['ap'].'/'.$get['ap'].'Action.class.php')) {
            if (in_array(getExt($_SERVER["PATH_INFO"]), $this->pic)) {
                 throw new Exception('无效的图片请求, 客户端IP '.$_SERVER['REMOTE_ADDR'], 505);
            };
            throw new Exception('类文件'.$get['ap'].'Action.class.php不存在, 客户端IP '.$_SERVER['REMOTE_ADDR'],505);
        }
        require_once($this->Controller.$get['ap'].'/'.$get['ap'].'Action.class.php');
        if (!class_exists($get['ap'].'Action')) {
            throw new Exception('类'.$get['ap'].'Action未定义',505);
        }
        //初始化
        $Mobile   = $this->isMobile();
        $HcacheFileName   = $this->getHASEname($get['op']);
        if ($Mobile) {
            $tplFilePosi   = $this->View.$get['ap'].'/'.'Mobile'.'/';
            $HcacheFilePosi= $this->Temp.$get['ap'].'/'.$get['op'].'/'.'Mobile'.'/';
            $PcacheFilePosi    = $this -> ClassData.$get['ap'].'/'.'Mobile'.'/';
        } else {
            $tplFilePosi   = $this->View.$get['ap'].'/';
            $HcacheFilePosi= $this->Temp.$get['ap'].'/'.$get['op'].'/';
            $PcacheFilePosi    = $this -> ClassData.$get['ap'].'/';
        }
        $tplFilePath       = $tplFilePosi.$get['op'].'.'.$this->TplExt;
        $HcacheFilePath    = $HcacheFilePosi.$HcacheFileName.'.'.$this->TplExt;
        $indexPHP          = $this->isRewrite ? rtrim($this->INDEX,'/') : $_SERVER['SCRIPT_NAME'];  
        $arr = array(
            'Function_' 	=> $get['op'],
            'Class_'    	=> $get['ap'],
            '__APP__'   	=> $indexPHP,
            '__URL__'   	=> $indexPHP.'/'.$get['ap'],
            '__FUN__'   	=> $get['op'],
            '__CLA__'   	=> $get['ap'],
            '__PATH__'      => $this->View.$get['ap'],
            '__INDEX__'     => $this->INDEX,
            'IsMobile'  	=> $Mobile,
            'tplFilePath'       => $tplFilePath,
            'tplFilePosi'       => $tplFilePosi,
            'tplFileName'       => $get['op'].'.'.$this->TplExt,
            'HcacheFilePath'    => $HcacheFilePath,
            'HcacheFilePosi'    => $HcacheFilePosi,
            'HcacheFileName'    => $HcacheFileName,
            'PcacheFilePath'    => $PcacheFilePosi.$get['op'].'.php',
            'PcacheFilePosi'    => $PcacheFilePosi,
            'PcacheFileName'    => $get['op'].'.php',
        );      		
        $config    = array_merge(get_object_vars($this), $arr);
        $get['ap'] = $get['ap'].'Action';
        $Action    = new $get['ap'];
        if (!session_id()) {
            session_start();
        }
        $Action   -> realy($config);
            if (isset($get['op'])) {
                if (!method_exists($Action,$get['op'])) {
                    throw new Exception('方法'.$get['op'].'未定义',505);
                }
            } else {
                throw new Exception('未知匿名方法',505);
            }	
        $function = $get['op'];
        unset($get);
        $Action->$function();
        //关闭资源 释放内存
        $Action->closeLink();
        if (isset($Action->db)) { 
            $Action->db->closeLink();
        }
    }
}
/**
 * 路由类
 * @author 武恒 <8000km.cn>
 * @param array   网站配置数组
 */
class Route 
{
    /**
     * 路由类初始化
     */
    public function __construct($config) {
        if (empty($config) || !is_array($config)) {
            throw new Exception("配置错误！",505);
        }
        foreach ($config as $k => $v) {
            $this->$k = $v;
        }
		//如果开启伪静态强制隐藏文件后缀
		if ($config["Rewrite"]) {
			if (!$this->isRewrite)
				throw new Exception("不允许动态访问",404);
		}
    }
    /**
     * 取二级域名
     * 目前之能取二级，以后考虑增强
     */
    public static function getHost() {
        $res  = false;
        $host = explode('.',$_SERVER["HTTP_HOST"]);
        if (count($host) >= 3 && $host[0] !== 'www') {
            $res = $host[0];
        }      
        return $res;
    }
    /**
     * 取路由
     */
    public function getRoute() {
        if (isset($_SERVER['PATH_INFO'])) {
            $_SERVER['PATH_INFO'] = trim($_SERVER['PATH_INFO'],'/');
        }
		//解析URL参数 使用为静态
		if (isset($_SERVER['PATH_INFO']) && $_SERVER['PATH_INFO'] && !empty($this->rewriteRule)) {	
			//首先取静态分页参数
				$pathInfo = $_SERVER['PATH_INFO'];
				$arr = explode('/',$pathInfo);	
				if (($p = end($arr))) {
                    if ($p[0] === 'p' && is_numeric($p[1])) {
                        $_GET['p'] = substr($p, 1);
                        $pathInfo  = substr($pathInfo, 0, strripos($pathInfo, '/')); 
                    }
                }
			//如果非正则最好
			if (isset($this->rewriteRule[$pathInfo])) {
				$_SERVER['QUERY_STRING'] = $this->rewriteRule[$pathInfo];   
			} else {
			//正则解析静态 取识别标志
				$pattern     = array_keys($this->rewriteRule);
				$replacement = array_values($this->rewriteRule);
				foreach ($pattern as $k => $v) {
					$res = preg_match_all('@'.$v.'@i', $pathInfo, $matches); 
					if ($res !== false && isset($matches[0][0]) && $matches[0][0] == $pathInfo) {
						$_SERVER['QUERY_STRING'] = preg_replace('@'.$v.'@i', $replacement[$k], $pathInfo, 1); 
					}
				}
			}
		}	
		//提取参数
        $info = array();
        if (!empty($_SERVER["QUERY_STRING"])) {
            $info  = array_merge($info, $this->getQuery($_SERVER["QUERY_STRING"]));	
        }
		if (!empty($_SERVER["PATH_INFO"])) {
            $info  = array_merge($info, $this->getInfo($_SERVER["PATH_INFO"]));
        }
		if ($info) {
			return $info;
		} else if (is_file($this->Controller.'Index/IndexAction.class.php')) {  
            $info  = $this->defaultfun();
        } else if (!is_file($this->Controller.'clock') && (!is_file($this->Config.'config.php'))) {
            $info  = false;
        } else {
            throw new Exception("应用错误！",505);
        }
        return $info;
   }
    /**
     * 取路径参数
     */
    private function getInfo($str = '') {
        if ($str == '') {
            return false;
        }	
        $arrInfo = array();
        $arr     = explode('/', $str); 
        //提取分页参数
        if (isset($_GET['p'])) {	    
            $_SERVER['QUERY_STRING'] = strtr($str,array('/p'.$_GET['p']=>''));
        }
        if ($arr[0] == 'favicon.ico') {
            stop();
        }	
        if (isset($arr[0])) {
            $arrInfo['ap'] = $arr[0];
            array_shift($arr);
        }	
        if (isset($arr[0])) {
            $arrInfo['op'] = $arr[0];
            array_shift($arr);
        }
        //最后一个去掉静态后缀    
        if (!empty($arr) && getExt($arr[count($arr)-1]) == $this->Suffix ) {
            $arr[count($arr)-1] = substr( $arr[count($arr)-1], 0, strpos($arr[count($arr)-1], '.'.$this->Suffix));
        }
        if (count($arr) % 2 != 0 && !empty($arr)) {
            array_pop($arr);
        }
        for ($i = 0; $i <count($arr); $i++) {	
            if($arr[$i] != ''){
                $_GET[$arr[$i]]    = $arr[1+$i];
                $arrInfo[$arr[$i]] = $arr[++$i];
            }
        }
        return $arrInfo;
    }
    /**
     * 取动态参数
     */
    private function getQuery($str) {
        if ($str == '') {
            return false;
        }
        $arrInfo = array();
        //去掉多余的&号
        $str     = preg_replace('/&+/','&',$str);	
        $arr     = explode('&',$str);
        //提取分页参数 
        if (isset($_GET['p'])) {
			$_SERVER['QUERY_STRING'] = strtr($_SERVER['QUERY_STRING'],array('&p='.$_GET['p']=>''));
        }
        foreach ($arr   as  $v) {
            $tm = explode('=', $v);
            if (isset($tm[0]) && isset($tm[1])) {
                $arrInfo[$tm[0]] = $tm[1];
            }
        }	
        return $arrInfo;
    }
    /**
     * 默认方法
     */
    private function defaultfun() {
        $arrInfo = array();
        $arrInfo['ap'] = 'Index';
        $arrInfo['op'] = 'index';
        return $arrInfo;
    }
}
/**
 * 框架控制层，为用户提供最基础逻辑控制工具。
 * @author 武恒 <8000km.cn>
 * @param array 网站配置数组
 */
class Action extends Db
{	
    protected $post;
    protected $get;
    protected $cookie;
   /**
    * 跨级导入参数
    */
    public function realy($config, $hook = false) {  
        if (empty($config) || !is_array($config)) {
            throw new Exception("配置错误！",505);
        }
        //初始化网站配置
        foreach ($config as $k => $v) {
            $this->$k = $v; 
        }
        //网站开关
        if ($this->WebOff != false) {
            $this->say($this->WebOff, null, 1111, '网站维护信息提示');
        }
        //导入公共函数
        if (is_file($this->Config.'common.php')) {
            include_once($this->Config.'common.php');
        }
        //驱动数据库
        $this->dataBases = array();           
        if (!empty($this->dbConfig) && ($db = simplexml_load_string($this->dbConfig)) != false) {
            $val      = array (); 
            foreach ( (array) $db as $key => $value ) { 
                foreach($value as $k => $v) {
                    $val[$k] =  (string)  $v;
                }
                $this->dataBases[$key] = ( array ) $val; 
            }     
        }
        //初次初始化判断
        if ($hook == true) {
            return;
        }  
        if ($this->InputCheck) {
            //阻止系统自动添加斜线  magic_quotes_sybase配置在5.4已经删除 所以做个判断
			if (version_compare("5.4", PHP_VERSION, ">") && ini_get('magic_quotes_gpc') == 1) {
				if (!empty($_POST)) {
					$_POST = $this->stripslashes_deep($_POST);
				}
				if (!empty($_GET)) {
					$_GET = $this->stripslashes_deep($_GET);
				}
				if (!empty($_COOKIE)) {
					$_COOKIE = $this->stripslashes_deep($_COOKIE);
				}
			}
			$this->post   = $_POST;
			$this->get    = $_GET;
			$this->cookie = $_COOKIE;
				if (!empty($_POST)) {
					 $_POST  = $this->autoFilter($_POST);
				}       
				if (!empty($_GET)) {
					$_GET    = $this->autoFilter($_GET);
				}
				if (!empty($_COOKIE)) {
					$_COOKIE = $this->autoFilter($_COOKIE); 
				}
			if ($this->InputCheck == 2) {
				if (!empty($_POST)) {
					$_POST   = $this->inputFilter($_POST);
				}       
				if (!empty($_GET)) {
					$_GET    = $this->inputFilter($_GET);
				}
				if (!empty($_COOKIE)) {
					$_COOKIE = $this->inputFilter($_COOKIE); 
				}
			} elseif ($this->InputCheck == 1) {
				if (!empty($_POST)) {
					$_POST   = $this->htmlFilter($_POST);
				}       
				if (!empty($_GET)) {
					$_GET    = $this->htmlFilter($_GET);
				}
				if (!empty($_COOKIE)) {
					$_COOKIE = $this->htmlFilter($_COOKIE); 
				}
			}
        }
        //执行钩子函数 此函数在 框架起始 中间 收尾三次执行
        if (isset($this->hook)) { 
            $this->hook->realy($config, true);
            $this->hook->begin();   
        }   
        if (is_file($this->Controller.$this->Class_.'/PreExe.class.php')) {
            include_once($this->Controller.$this->Class_.'/PreExe.class.php');
            $PreExe = new PreExe();
            $PreExe-> realy($config, true);
            $this -> preExe = $PreExe -> func();
        }
        //驱动M层
        $db_c   = array(
            'CheckSql'      => $this->CheckSql,
            'SQLslow'       => $this->SQLslow,
            'SQLtime'       => $this->SQLtime,
            'LogLevel'      => $this->LogLevel,
            'Logs'          => $this->Logs,
            'CloseError'    => $this->CloseError
        ); 
        $this->dataBase  = current($this->dataBases);
        $this->dbInit  = array_merge(array('dataBases'=>$this->dataBases, 'dataBase'=>$this->dataBase), $db_c);
         if ( is_file(($dbFile = $this->Controller.$this->Class_.'/'.$this->Class_.'Db.class.php'))) {  
            require_once($dbFile); 
            if (class_exists($this->Class_.'Db')) {
                $class    = $this->Class_.'Db'; 
                $this->db = new $class;
                $this->db->realy($this->dbInit);
            }
        }
    }
    /**
     * 三级过滤 禁止使用反义斜线
     */
    protected function autoFilter($arr) {   
       foreach ((array)$arr as $k => $v) {
           if (is_array($v)) {
                $arr[$k] = $this->autoFilter($v);
           } else {
                //前面去掉系统转义 这里手工转义 保证用户不能使用转义字符
                if (version_compare("5.2", PHP_VERSION, ">")) {
                    $arr[$k] = strtr ( $arr[$k] , array('\\'=>'\\'));
                } else {
                    $arr[$k] = strtr ( $arr[$k] , array('\\'=>'\\\\'));
                } 
           }
       }
       return $arr;
    }
	/**
     * 二级过滤 过滤重点危险字符
     */
    protected function inputFilter($str) {
        if(is_array($str)){
            foreach($str as $k => $v){
                $str[$k] = $this->inputFilter($v);
            }
            return $str;
        }
        $sarr = array(
            '/<script/i',   '/<iframe/i', '/<frameset/i', 
            '/<frame/i',    '/<applet/i', '/<meta/i',
            '/<a(.*?)script:(.*?)>/i',    '/<object/i',       
            '/<img(.*?)onerror(.*?)>/i',  '/<form/i', '/<style/i'
        );
        $rarr = array(
                '&lt;script',   '&lt;iframe',   '&lt;frameset', 
                '&lt;frame',    '&lt;applet',   '&lt;meta',  
                '&lt;a$1script&#58;$2>',        '&lt;object',    
                '<img$1error$2>', '&lt;form',   '&lt;style'
        );
		return preg_replace($sarr, $rarr, $str);
    }
	/**
	 * 一级过滤 过滤一切危险字符
	 */
	protected function htmlFilter($data){
		//转义HTML标签
		$data = is_array($data) ?
            array_map(array($this,'htmlFilter'), $data) :
            htmlspecialchars(trim($data), ENT_QUOTES, 'UTF-8');
        return $data;	
	} 
    /**
     * 自动验证
     * @param string $xmlName 过滤模版
     * @param bool $flag 是否走模版跳转标识
     */
    protected function aotoVerify($xmlName = 'aotoVerify', $datas = array(), $flag = true) {
        if (empty($datas)) {
            $datas[] = (!empty($_POST)) ?  $_POST : $_GET ;
        }
        if (empty($datas)) {
            return true;
        }
        $xmlFile    = $this->Controller.$this->Class_.'/'.$xmlName.'.php'; 
        if (is_file($xmlFile) && $xmlContent = file_get_contents($xmlFile)) {
            if (mb_convert_encoding($xmlContent,'UTF-8','UTF-8') !== $xmlContent) { 
              $xmlContent = iconv('gb2312', 'utf-8', $xmlContent);
            }
            $xml = simplexml_load_string($xmlContent);
        } else {
            throw new Exception("自动验证配置文件不存在",303);
        }
        $xml  = $this->xmlArray($xml);
        $info = null;
		if (is_array($xml)) {
			foreach ($xml as $v) {
				foreach ($datas as $data) {   
					if (isset($data[$v['name']])) {
						switch($v['type']){
							case 'regex':
								if (preg_match($v['value'],$data[$v['name']]) == 1) {
								   $info = $v['msg'];
								}
							break;
							case 'unique':
								if (!isset($v['value'])) {
									throw new Exception("自动验证配置项".$v['name']."有误",303);
								}
								if (empty($data[$v['name']])) {
									 $info = $v['msg'];
								} else {
									list($database, $table, $unit) = explode("-", $v['value']); 
									$this->useDataBase($database);
									$sql = $this->Select($table, $unit, array($unit));  
									$res = $this->execute($sql,array($data[$v['name']]));   
									if(!empty($res)){
										$info = $v['msg'];
									}
								}
							break;
							case 'notnull':
								if (empty($data[$v['name']])) {
									$info = $v['msg'];
								}
							break;
							case 'email':
								$reg = '/^[0-9a-z_][_0-9a-z-]{0,32}@([0-9a-z][0-9a-z-]{0,32}\.){1,32}[a-z]{1,8}$/i';
								if (!preg_match($reg,$data[$v['name']]) == 1) {
									$info = $v['msg'];
								}
							break;
							case 'url':
								if (substr($data[$v['name']],0,7) != 'http://' && 
									substr($data[$v['name']],0,8) != 'https://'&&
									substr($data[$v['name']],0,6) != 'ftp://') {
									$data[$v['name']] = 'http://'. $data[$v['name']];
								}
								$reg = '/^(http|https|ftp)\:\/\/([\w-]+\.)+[\w-]+(\/[\w-.\/?%&=]*)?$/i';
								if (!preg_match($reg,$data[$v['name']]) == 1) {
									$info = $v['msg'];
								}
							break;
							case 'number':
								if (!is_numeric($data[$v['name']])) {
									$info = $v['msg'];
								} else if (isset($v['value'])) {
									$info = $this->range($data, $v['value'], $v['name'], $v['msg']);
								}
							break;
							case 'int': 
								if (strstr($data[$v['name']], '.') || !is_numeric($data[$v['name']])) {
									$info = $v['msg'];
								} else if (isset($v['value'])) {
									$info = $this->range($data, $v['value'], $v['name'], $v['msg']);
								}
							break;
							case 'string':
								if (!is_string($data[$v['name']])) {
									$info = $v['msg'];
								} else if (isset($v['value'])) {
									$info = $this->long($data, $v['value'], $v['name'], $v['msg']);
								}
							break;
							case 'long':
								if (!isset($v['value'])) {
									throw new Exception("自动验证配置项".$v['name']."有误",303);
								} 
								$info = $this->long($data, $v['value'], $v['name'], $v['msg']);
							break;
							case 'confirm':
								if (!isset($v['value'])) {
									throw new Exception("自动验证配置项".$v['name']."有误",303);
								}   
								if ( $data[$v['name']] !== $data[$v['value']] || empty($data[$v['name']])) {
									$info = $v['msg'];
								}
							break;
							case 'tel':  
								$reg = '/^1[3|4|5|8]\d{9}$/';
								if (!preg_match($reg,$data[$v['name']]) == 1) {
									$info = $v['msg'];
								}
							break;
							case 'callback':
								if (!isset($v['value']) || !method_exists($this,$v['value'])) {
									throw new Exception("自动验证配置项".$v['name']."有误",303);
								}
								if (!call_user_func_array(array($this,$v['value']), array($data[$v['name']]))) {
									$info = $v['msg'];
								}
							break;
							default:
							break;
						}
						if (!is_null($info)) {
							if ($flag == true) {
								$this->say($info);
							} else {
								return false;
							}
						}
					}
				}
			}
		}
        return true;
    }
    /**
     * 判断范围
     */
    private function range($data, $value, $name, $msg) {
        $info = null;
        if (strstr($value, ',')) {
            $arr = explode(',',$value);
            if (!in_array($data[$name],$arr)) {
                $info = $msg;
            }
        } else if (strstr($value, '-')) {
            list($min, $max) = explode("-", $value);
            if (!( $data[$name] >= $min && $data[$name] <= $max ) ) {
                $info = $msg;
            }
        } else {
            if ($data[$name] != $value) {
                $info = $msg;
            }
        }
        return  $info;
    }
    /**
     * 判断长度
     */
    private function long($data, $value, $name, $msg) {
         $info = null;
         if (strstr($value, '-')) {
            list($min, $max) = explode("-", $value);
            if (!( strlen($data[$name]) >= $min && strlen($data[$name]) <= $max ) ) {
                $info = $msg;
            }
        } else {
            if ($data[$name] != $value) {
                $info = $msg;
            }
        }
        return $info;
    }
    /**
     * 解析xml
     */
    private function xmlArray($xml) {
        if (is_object($xml)){
            $xml   = (array) $xml;
            $array = array();
        } else {
            return false;
        }
        foreach ($xml as $k => $v) {
            (is_object($v)) ? $v = (array) $v : '';
            if (isset($v[0]) && is_object($v[0])) {
                foreach ($v as $z) {
                    $array[] = $this->xmlArray($z);
                }
            } else if (isset($v['@attributes'])) {
                $array[] = $v['@attributes'];
            } else {
                $array   = $v;
            }
        }    
        return $array;
    }
    /**
     * 取model
     * @param string $className model所属类
     */
    protected function getModel($className){
        $file = $this->Controller.'/'.$className.'/'.$className.'Db.class.php';
        if (is_file($file)) {
            require_once($file);
            $className .= 'Db';   
            $dbObj = new $className;
            $dbObj->realy($this->dbInit);
            return $dbObj;
        } else {
            throw new Exception("getmodel函数必要参数".$className."有误",303);
        }
    }
    /**
     * 控制重复提交
     */
     protected function subs($set = null){
         if (empty($set)) {
            if (!isset($_SESSION['sub'])) {
                $this->say('请不要重复提交数据哦！');
            } else {
                unset($_SESSION['sub']);
            }
         } else {
             $_SESSION['sub'] = $set;
         } 
     }
    /**
     * 去斜线
     */
     public function stripslashes_deep($value) {
        $value = is_array($value) ?
            array_map(array($this,'stripslashes_deep'), $value) :
            stripslashes($value);
        return $value;
    }
    /**
     * 分页函数 内部调用
     */
	private function  page($url = null,$getpage = 1,$data = 1,$num = 10,$r = 5) {	
        if (empty($url)) {
            $type = true;
            $url  = $this->__APP__.'?'.$_SERVER['QUERY_STRING'];
        } else {    
            $url  = $this->INDEX.$url;
        }  
        $first = 1;										
        $end   = $num < $data?ceil( $data/$num):1;		
        if ( is_numeric( $getpage)&&( $getpage <= $end && $getpage >= $first)) {
            $page = $getpage;
        } else {
            $page = 1;
        }
		if ( $end >= 2 * $r + 1) {													
            if ( $page <= $r) {
                $firstpage_r = 1;    				
            } else {
                $firstpage_r = $page-$r;				
                if ($page > $end - $r) {					
                    $firstpage_r = $end - 2*$r;		
                }
            }
            if ( $page >= $end - $r) {						
                $endpage_r = $end;					 		
            } else {		
                $endpage_r = $page + $r;				
                if ( $page <= $r) {		 
                 $endpage_r = 2 * $r + 1;
                } 
            }
		} else {
            $firstpage_r = $first;
            $endpage_r   = $end;	
		}
		//样式
            $return = <<<EF
<style>
	#pageSub{
	  border:none;
	  background-color:#DEE3E7;
	  color:#30A0EC;
	  height:25px;
	  font-size:18px;
	}
    #page a {
	  border: #dee3e7 solid 1px;
	  text-align: center;
	  color: #30A0EC;
	  margin-left: 5px;
	  text-decoration: none;
	  padding: 4px 7px;
	  border-radius: 3px;
    }
    #page a:hover{
        background-color:#30A0EC;
        color:#FFFFFF;
    }
</style>
EF;
        if (!isset($type)) { 
            $return.="<center><form id = 'page' action=".$url." method='post'><a href='".$url."/p1'>首页</a>";
            if ( $page > $firstpage_r) {
                $return .= "<a href='".$url."/p".($page-1)."'>上一页</a>";
            } else {
                $return .= "<a href='#'>上一页</a>";
            }
             for ( $i = $firstpage_r; $i <= $endpage_r; $i++) {
                if ( $i == $page) {
                    $return .= "<a href='#'style='background-color:#30A0EC;color:#FFFFFF;'>第[".$i."]页</a>";
                } else {
                    $return .= "<a href='".$url."/p".$i."'>第".$i."页</a>";
                }
            }
            if ( $page < $endpage_r) {
                $return .= "<a href='".$url."/p".($page+1)."'>下一页</a>";
            } else {
                $return .= "<a href='#'>下一页</a>";
            }
            $return .= "<a href='".$url."/p".$end."'>尾页</a></form></center>";
        } else {
            $return.="<center><form id = 'page' action=".$url." method='post'><a href='".$url."&p=1'>首页</a>";
            if ( $page > $firstpage_r) {
                $return .= "<a href='".$url."&p=".($page-1)."'>上一页</a>";
            } else {
                $return .= "<a href='#'>上一页</a>";		
            }
            for ( $i = $firstpage_r; $i <= $endpage_r; $i++) {
                if ( $i == $page) {
                    $return .= "<a href='#'style='background-color:#30A0EC;color:#FFFFFF;'>第[".$i."]页</a>";
                } else {
                    $return .= "<a href='".$url."&p=".$i."'>第".$i."页</a>";
                }
            }
            if ( $page < $endpage_r) {
                $return .= "<a href='".$url."&p=".($page+1)."'>下一页</a>";
            } else {
                $return .= "<a href='#'>下一页</a>";
            }
            $return .= "<a href='".$url."&p=".$end."'>尾页</a>";
            $return .= "<input type='text' name='p' style='width:30px;margin-left:5px; border: #CCC solid 1px;height:23px;'>
                        <input type='submit' id='pageSub' name='sub' value='跳页'/></form></center>";	 
        }
        $this->assign('dreamPage',$return);
	}
    /**
    * 分页接口 
    * @param string $sql   正常查询数据的sql语句
    * @param int    $num   每页显示数【可选】
    * @param int    $r     页码半径【可选】
    * @param string $Param 附加参数【可选】
    * @param string $url   返回的url【可选】
    * @return array	    查询的数据
    */
	protected function getPage($sql,$url = null,$num = 10,$r = 5){    
        if ( isset($_GET['p'])) {
            $page = $_GET['p'];
        } else {
            $page = 1;
        }
        $numSql = "SELECT COUNT(*) AS num " . substr($sql, stripos($sql, 'FROM'));
		if (strripos($numSql,"GROUP BY")) {
			$numSql = "SELECT COUNT(*) FROM (" . $numSql . ") AS A";
		} 
        $sp = NULL;
        if ( is_numeric($page)){
            $sp = $page  * $num - $num;
        }
        $data = $this->query($numSql);  
        if ( empty($sp) || $sp > ($data['num'] / $num)){
            $sp = 0;
        }  
        $this ->page($url,$page,$data['num'],$num,$r); 
        return  $this->query($sql.' LIMIT '.$sp. ',' .$num); 
	}
   /**
    * 信息输出跳页 
    * @param string $info   输出语句
    * @param string $url    跳页地址
    * @param string $t      等待时间
    * @param string $title  提示标题
    */
    protected function say($info = '操作成功！',$url = NULL,$t = 6,$title = '信息提示') {
	$u   = isset($_SERVER['HTTP_REFERER'])?$_SERVER['HTTP_REFERER']:$this->WebUrl;
        $url = empty($url)?$u:$url;
        if ($t == 0) {
            Header( 'Location:'.$url );
            stop();
	}
        $msg = array(
            't'    => $t,
            'url'  => $url,
            'info' => $info,
            'title'=> $title
        );
        $this->assign('msg',$msg);
		$infoPath = $this->IsMobile ? $this->_InfoTpl_.'Mobile/info.html' : $this->_InfoTpl_.'info.html';
        $this->_execute($infoPath, false);
        stop();
    }
    /**
     * 输出消息
     * @param string $res    判断条件
     * @param string $info   输出语句 可以是字符串或数组，字符串用中文逗号隔开
     * @param string $url    跳页地址
     */
    protected function message ($res, $info = '操作成功|操作失败', $r = null, $e = null) {
        if (is_string($info)) {
            $info = explode('|', $info);
        }
		$h = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : $this->INDEX;
		$r = (empty($r)) ? $h : $r;
		$e = (empty($e)) ? $r : $e ;
		if (is_array($res)) {
			foreach ($res as $v) {
				if ($v === false) {
					$res = false;
					break;
				}
			}
			if ($res !== false) {
				$res = true;
			}
		}
        if ($res === false) {
            $this->say($info[1], $e);
        } else {
			$this->say($info[0], $r);
        }
    }
    /**
     * 布局函数
     * @param string $name 使用的模版名称
     * @return void
     */
    protected function layout( $name = 'layout') {
        if ($name != false) {
            $this-> Layout     = true;
            $this-> LayoutName = $name;
        } else {
            $this-> Layout     = false;
        }
    }
    /**
     * 删除缓存
     * @return bool
     */
    protected function clearHtml() {
        return  delDir($this->HcacheFilePosi,false);
    }
}
/**
 * 模版替换类  框架V层
 * @author 武恒 <8000km.cn>
 * @param array 配置数组
 */
class Tpl
{                
    private  $tpl_vars = array();
    /**
     *初始化配置
     */
    public function __construct(){
        if (func_num_args() > 0) {
            $config =  func_get_arg(0);
            if (!empty($config) && is_array($config)) {
                foreach ($config as $k => $v) {
                    $this->$k = $v;
                }
            }
        }
    }
    /**
     *为模版内变量赋值 
     *@param string $tpl_var 前台变量名字
     *@param mixed $value 变量值
     *@return void 
     */
    public function assign($tpl_var, $value = null) {
        if ($value == null && is_array($tpl_var)) {
            foreach ( $tpl_var as $k => $v) {
                $this->tpl_vars[$k] = $v;
            }
        } else if ($tpl_var != null) {
            $this->tpl_vars[$tpl_var] = $value;
        }
    }
    /**
     * 执行模版替换操作
     */
    private function tpl_replace($content) {
        $content = $this->tpl_layout($content);
        $this->tpl_check($content);
        $this->forT = $this->ifT = $this->foreachT =  0;  		
        $content = $this->tpl_include($content, $this->tplFilePosi); 
        $content = $this->tpl_literal($content);
		$content = $this->tpl_notes($content);
        $content = $this->tpl_const($content);
        $content = $this->tpl_cUrl($content);
        $content = $this->tpl_foreach($content);     
        $content = $this->tpl_if($content);      
        $content = $this->tpl_else($content);     
        $content = $this->tpl_for($content);
        $content = $this->tpl_tyor($content);
        $content = $this->tpl_func($content);
        $content = $this->tpl_variable($content);    
        $content = $this->tpl_CusVar($content);         
        $content = $this->tpl_end($content);      
        $content = $this->tpl_src($content);      
        $content = $this->tpl_literal_r($content);
        $this->tpl_num($content);
        if($this->ZipCode) {
            $find           = array('~>\s+<~','~>(\s+\n|\r)~');
            $replace        = array('><','>');
            $content        = preg_replace($find, $replace, $content);
            $strtr          = array('?><?php' => '');
            $content        = strtr( $content,$strtr);
        }
        return  '<?php if (!defined(\'SIGN\')) exit(0);?>'.$content;
    }
    /**
     * 执行静态模版引入 
     * @param string $fileName 模版名
     * @param string $controller 控制类名
     * @return void
     */  
    public function makeHtml($fileName = '',$controller = ''){  
        $tplFilePath = $this->getFilePath( $fileName, $controller);
        if ( !is_readable($tplFilePath)) {
            throw new Exception("模板文件".$tplFilePath."不可读!",303);  
        }
        extract($this->tpl_vars, EXTR_OVERWRITE);
        if ($this->MakeHtml) {   
            if (!is_file($this->PcacheFilePath) || filemtime($this->PcacheFilePath) < filemtime($tplFilePath) || !$this->Cache) { 	
                $tplFileContent = file_get_contents($tplFilePath);							
                $repContent     = $this->tpl_replace( $tplFileContent);  
                if ( !is_dir( $this->PcacheFilePosi)) {
                    new MakeDir( $this->PcacheFilePosi);
                }
                @file_put_contents( $this->PcacheFilePath, $repContent, LOCK_EX);
                if (!is_readable($this->PcacheFilePath)) { 
                    throw new Exception('缓存文件'.$this->PcacheFilePath.'不可读',303);
                }
            }
            if (!is_dir($this->HcacheFilePosi)) {
                new MakeDir($this->HcacheFilePosi);
            }
            $str = '';
            ob_start();
            require ($this->PcacheFilePath);
            $str = ob_get_clean();
            ob_end_clean();   
            echo $str;
            @file_put_contents( $this->HcacheFilePath, $str, LOCK_EX);
        }
        if (!is_readable($this->HcacheFilePath)) { 
            throw new Exception('缓存文件'.$this->HcacheFilePath.'不可读',303);
        }
        require ($this->HcacheFilePath);    
    }
    /**
     * 执行动态模版引入
     * @param string $fileName 模版名
     * @param string $controller 类名
     * @return void
     */ 
    public function display($fileName = '',$controller = '') {   
        $this->_execute( $this->getFilePath( $fileName, $controller));
    }
    /**
     * 得到路径
     */ 
    private function getFilePath( $fileName, $controller) {	
        if ($fileName == '' && $controller == '') {	
            $return = $this->tplFilePath;
        }
        if ($controller == '') {
            $controller = $this->Class_;
            if ($this->IsMobile) {
                $controller .= '/'.'Mobile';
            }
        }
        if ($fileName == '') {
            $fileName   = $this->Function_;
        }
        $return = $this->View.$controller.'/'.$fileName.'.'.$this->TplExt;
        //如果手机文件不存在 使用PC文件
        if ($this->IsMobile && !is_file($return)) { 
            $controller = substr($controller, 0, -7);
            $this->tplFilePosi = substr($this->tplFilePosi, 0, -7);
            $return = $this->View.$controller.'/'.$fileName.'.'.$this->TplExt;
        } 
        return $return;
    }
    /**
     * 执行
     * @param string $tplFilePath 模版路径
     * @param bool $cache 是否走php缓存
     * @return void
     */ 
    public function _execute( $tplFilePath, $cache = true) { 
		if (!is_file($tplFilePath)) {
            throw new Exception("模板文件".$tplFilePath."不存在!",303);
        }
        if (!is_readable($tplFilePath)) {
            throw new Exception("模板文件".$tplFilePath."不可读!",303);
        }
        extract($this->tpl_vars, EXTR_OVERWRITE);
        if (!isset($this ->tplFileName)) {
            $strIndexName       = basename($tplFilePath);
            $this ->tplFileName = substr($strIndexName,0,strripos($strIndexName,'.'));
        }  
        if (!is_file($this->PcacheFilePath) || filemtime($this->PcacheFilePath) < filemtime($tplFilePath) || !$cache || !$this->Cache) {   
            $tplFileContent = file_get_contents($tplFilePath);							
            $repContent     = $this->tpl_replace($tplFileContent);
            if ($cache) {
				if ( !is_dir( $this->PcacheFilePosi) ) {
					new MakeDir( $this->PcacheFilePosi);
				}
                @file_put_contents($this->PcacheFilePath, $repContent, LOCK_EX);
                $require = $this->PcacheFilePath; 
            } else {
				if ( !is_dir( $this->Temp) ) {
					new MakeDir( $this->Temp );
				}
				@file_put_contents($this->Temp . 'tmp.php', $repContent, LOCK_EX);
                $require = $this->Temp."tmp.php";	
			}	
        } else {
            $require = $this->PcacheFilePath;
        }
        if (!is_readable($require)) {
            throw new Exception("模板文件".$require."不可读!",303);
        }
        require ($require);
    }
    /**
     * include 检查
     */ 
    private function tpl_include($tplFileContent, $path) {  
        $matches    =   array();
        $num        =   preg_match_all('/'.$this->TplL.'\s*include\s*\(?(.+?)\)?\s*'.$this->TplR.'/ie',$tplFileContent,$matches);
        if ($num   != false) {
            $strtr  = array(); 
            for ($i = 0; $i < $num; $i++) {   
                if (substr( $matches[1][$i], 0, 1 ) == '$') {
                    $matches[1][$i] = $this->tpl_vars[substr( $matches[1][$i], 1)].'.'.$this->TplExt;
                }
                $tempFile   =   realpath($this->addPoint($path.$matches[1][$i])); 
                if ( !$tempFile) {
                    $includeStr          = "<p style='color:red;width:100%;word-wrap:break-word;'>引入文件".$path.$matches[1][$i]."不存在！</p>";
                } else {
                    $includeStr    		 = file_get_contents($tempFile);   
                }
                $strtr[$matches[0][$i]]  = $includeStr;
            }
           $tplFileContent               =   strtr($tplFileContent,$strtr);
           $this->tpl_include($tplFileContent, $this->tplFilePosi);
        }
        return $tplFileContent;
    }
    /**
     * layout 检查
     */ 
    private function tpl_layout($tplFileContent) {               
        if (strpos($tplFileContent,$this->TplL.'__NOLAYOUT__'.$this->TplR) !== false) { 
            $strtr          = array($this->TplL.'__NOLAYOUT__'.$this->TplR => '');
            $tplFileContent = strtr( $tplFileContent, $strtr);   
        } else if ( $this->Layout != false) { 
            $layoutFile     = $this->LayoutPath.$this->LayoutName.'.'.$this->TplExt;
            if ( !is_file($layoutFile)) {
                throw new Exception('布局文件'.$layoutFile.'不存在',303);
            }
            $layout         =  file_get_contents($layoutFile);
            $layout         =  $this->tpl_include($layout ,$this->LayoutPath); 
            $strtr          =  array($this->TplL.$this->LayoutContent.$this->TplR => $tplFileContent);
            $tplFileContent =  strtr($layout, $strtr);
        }
        return $tplFileContent; 
    }
    /**
     * literal 屏蔽内容检查
     */ 
    private  function tpl_literal($tplFileContent) {
       if (!isset($this->Literal)) { 
           $this->Literal = array();
       }
       $matches = array();
       $num      =   preg_match_all('/'.$this->TplL.'literal'.$this->TplR.'([\s\S]*)'.$this->TplL.'\/literal'.$this->TplR.'/ie',$tplFileContent,$matches);
       if ($num != false) {
           for ($i = 0; $i < $num; $i++) {
               $x  =   count($this->Literal);
               $this->Literal[$x] =   $matches[1][$i];
               $strtr[ $matches[0][$i]]   =   "<!--###literal".$x."###-->";
           }
           $tplFileContent     =   strtr( $tplFileContent, $strtr);
       }
       return $tplFileContent;
    }
    /**
     * addPoint 转变前台点数组为标准数组
     */ 
    private function addPoint($var) {	
        $match = array();
        $num   = preg_match_all('/(\$[\w\[\]\'\"]+)\.(\w+)/', $var, $match);   
        if ($num != false) {
            $strtr = array();   
            for ($i = 0; $i< $num; $i++) {  
                $strtr[$match[0][$i]] = $match[1][$i].'["'.$match[2][$i].'"]';
            }
            $var = $this->addPoint(strtr( $var, $strtr)); 
        }
        return $var;
    }
    /**
     * Variable 输出变量
     */ 
    private function tpl_variable($tplFileContent) {
        $matches = array();
        $num = preg_match_all('/'.$this->TplL.'\s*(\$.[^\|:]+?)\s*'.$this->TplR.'/ie',$tplFileContent,$matches);
        if ($num != false) {
            $strtr = array();
            for ($i = 0; $i < $num; $i++) {
                $var 	 =  $this->addPoint($matches[1][$i]);
                $strtr[$matches[0][$i]] = '<?php if (isset('.$var.')) echo '.$var.'; ?>';
            }
          $tplFileContent  =  strtr( $tplFileContent, $strtr);
        }
        return $tplFileContent;
    }
    /**
     * foreach 检查
     */
    private function tpl_foreach($tplFileContent) {
        $matches = array();
        $pre = '/'.$this->TplL.'\s*foreach\s+(\$.+?)\s+as\s+(.+?)'.$this->TplR.'/ie';
        $num = preg_match_all($pre,$tplFileContent,$matches);
        $this->foreachT += $num;
        if ($num != false) {
            $strtr = array();
            for ($i = 0; $i < $num; $i++) {
                $var 	       =  $this->addPoint($matches[1][$i]);
                $strtr[$matches[0][$i]] = '<?php if (isset('.$var.')) foreach ( '.$var.' as '.$matches[2][$i].') : ?>';
            }
            $tplFileContent  =   strtr(  $tplFileContent,$strtr);
        }
        return $tplFileContent;
    }
    /**
     * if || else if 检查
     */
    private function tpl_if($tplFileContent) {
        $matches = array();
        $num = preg_match_all('/'.$this->TplL.'\s*(else){0,1}if\s*(.+?)\s*'.$this->TplR.'/ie',$tplFileContent,$matches);
        if ($num != false) {
            $strtr = array();
            for ($i = 0; $i < $num; $i++) {
                $var =  $this->addPoint($matches[2][$i]); 
                if ($matches[1][$i] == '') {
                    $this->ifT ++;
                    $strtr[$matches[0][$i]]  =   '<?php if ( '.$var.' ) : ?>';
                } else {
                    $strtr[$matches[0][$i]]  =   '<?php else if ( '.$var.' ) : ?>';
                }
            }
           $tplFileContent =   strtr( $tplFileContent,$strtr);
        }
        return $tplFileContent;
    }
    /**
     * else 检查
     */
    private function tpl_else($tplFileContent)	{
        $matches = array();
        $num = preg_match_all('/'.$this->TplL.'\s*else\s*'.$this->TplR.'/ie',$tplFileContent,$matches); 
        if ($num != false) {
            $strtr = array();
            for ($i = 0; $i < $num; $i++) {
                $strtr[$matches[0][$i]]    =   '<?php else: ?>';
            }
            $tplFileContent   =   strtr( $tplFileContent, $strtr);
        }
            return $tplFileContent;
    }
    /**
     * 结束符检查
     */
    private function tpl_end($tplFileContent)	{
        $arr = array( '/foreach'=>'endforeach', '/if'=>'endif','/for'=>'endfor');
        $matches = array();
        foreach ( $arr as $k => $v ) {
            $num = preg_match_all('&'.$this->TplL.'\s*('.$k.')\s*'.$this->TplR.'&ie',$tplFileContent,$matches);
            if($v == 'endforeach' && $num !== $this->foreachT) { throw new Exception('foreach 标签错误！',303);}
            if($v == 'endif'      && $num !== $this->ifT)      { throw new Exception('if 标签错误！',303);}
            if($v == 'endfor'     && $num !== $this->forT)     { throw new Exception('for 标签错误！',303);}
            if ($num != false) {   
                $strtr = array();
                for ($i = 0; $i < $num; $i++) {
                    $strtr [$matches[0][$i]]   =   '<?php '.$arr[$matches[1][$i]].'; ?>';
                }
                $tplFileContent   =   strtr( $tplFileContent,$strtr);
            }
        }
        return $tplFileContent;
    }
    /**
     *  原生语句输出
     */
    private function tpl_CusVar($tplFileContent) {
        $matches = array();
        $num = preg_match_all('/'.$this->TplL.'php\s+(.*?)?'.$this->TplR.'/ie',$tplFileContent,$matches); 
        if ($num != false) {
            $strtr = array();
            for ($i = 0; $i < $num; $i++) {
                if ($matches[1][$i] == '' ) { continue;}
                $strtr[$matches[0][$i]]    =   '<?php '.$matches[1][$i].'; ?>';
            }
            $tplFileContent     =   strtr( $tplFileContent,$strtr);
        }
        return $tplFileContent;
    }
    /**
     * 前台常量检查
     */
    private function tpl_const($tplFileContent)	{
        $tag = '__APP__|__URL__|__PUBLIC__|__PATH__|__FUN__|__CLA__|__INDEX__';
        if (isset($this->userDefined)) {
            foreach ($this->userDefined as $k => $v) {
               $tag .= '|'.$k; 
            }
        }
        $matches = array();
        $num = preg_match_all('/'.$tag.'/',$tplFileContent,$matches); 
        if ($num != false) {
            $strtr = array();
            for ($i = 0; $i < $num; $i++) {
                if (isset($this->$matches[0][$i])){
                    $strtr[$matches[0][$i]]    =    $this->$matches[0][$i];
                } else {
                    $strtr[$matches[0][$i]]    =    $this->userDefined[$matches[0][$i]];
                }
            }
            $tplFileContent    =   strtr( $tplFileContent,$strtr);
        }
        return $tplFileContent;
    }
    /**
     * 标示符检查
     */
    private function tpl_num($tplFileContent)	{
        $f = substr_count($tplFileContent,$this->TplL);
        $r = substr_count($tplFileContent,$this->TplR);
        if ( $f == $r) {
            return true;
        } else if ( $f > $r) {
            throw new Exception('缺少 '.$this->TplR.' 标签！',303);
        } else {
            throw new Exception('缺少 '.$this->TplL.' 标签！',303);
        }
    }
    /**
     * 模版标记检查
     */
    private function tpl_check($tplFileContent)	{
        $left    = preg_quote($this->TplL,'/');
        $right   = preg_quote($this->TplR,'/');
        $arr = array(
            'foreach'    => '/foreach',
            'if'         => '/if',
            'literal'    => '/literal',
            'for '       => '/for'
        );
        foreach ($arr as $k => $v) {
            $t = array();
            $f = preg_match_all('&'.$left.'\s*'.$k.'&',$tplFileContent,$t);
            $r = preg_match_all('&'.$left.'\s*'.$v.'\s*'.$right.'&',$tplFileContent,$t);
            if ( $f == $r) {
                continue;
            } else if ( $f > $r) {
               throw new Exception('缺少 '.$v.' 标签！',303);
            } else {
               throw new Exception('缺少 '.$k.' 标签！',303);
            }
        }
        return true;
    }
    /**
     * for 语句检查
     */
    private function tpl_for($tplFileContent) {
        $matches = array();
        $num = preg_match_all('/'.$this->TplL.'\s*for\s+(.+?)?'.$this->TplR.'/ie',$tplFileContent,$matches); 
        $this->forT += $num;
        if ($num != false) {
            $strtr      = array();
            for ($i = 0; $i < $num; $i++) {
                $parseStr     =     '<?php for (';
                $parseStr    .=     $this->addPoint($matches[1][$i]).') :';
                $parseStr    .=      '?>';
                $strtr[$matches[0][$i]] = $parseStr;
            }
            $tplFileContent     =   strtr( $tplFileContent,$strtr);
        }
        return $tplFileContent;
    }
    /**
     * literal屏蔽语句还原
     */
    private function tpl_literal_r($tplFileContent) {
        $matches = array();
        $num    = preg_match_all('/<!--###literal(\d+)###-->/ie',$tplFileContent,$matches);
        $strtr  = array();
        if ($num != false) {
            for ($i = 0; $i < $num; $i++) {
                $strtr[$matches[0][$i]] =    $this->Literal[$matches[1][$i]];  
            }
           $tplFileContent    =  strtr( $tplFileContent,$strtr);
        }
        return $tplFileContent;
    }
    /**
     * 处理src相对路径
     */
    private function tpl_src($tplFileContent) {
        $matches = array(); 
        $num   =   preg_match_all('%(src\s*=\s*[\"|\'])(?!http://|https://|ftp://|/|#)(.*?[\"|\'])%i',$tplFileContent,$matches);
        if ($num != false) {   
            $strtr =   array( $_SERVER['DOCUMENT_ROOT'] => '');
            $src   =   strtr($this->tplFilePosi, $strtr);  
            $strtr =   array();
            for ($i = 0; $i < $num; $i++ ) {	
                $strtr[$matches[1][$i]] = $matches[1][$i].$src.$matches[2][$i];
            }
            $tplFileContent    =   strtr( $tplFileContent,$strtr);
        }
        return $tplFileContent;
    }
    /**
     * 检查缓存
     * @return bool
     */
    protected function checkHtml() {		
        if (!$this->Cache || !is_file($this->HcacheFilePath)|| filemtime($this->HcacheFilePath) < filemtime($this->tplFilePath)){
            $state = true;			
        } else if ($this->HtmlCacheTime == 0 || (filemtime($this->HcacheFilePath) + $this->HtmlCacheTime - time()) > 0) {
            $state = false;
        } else {
            $state = true;		
        }
        $this->MakeHtml = $state;
        return $state;	
    }
	/**
	 * 管道符递归执行函数 :-) 
	 */
	private function tpl_func($tplFileContent) {
		$matches = array();
        $num = preg_match_all('@'.$this->TplL.'(([\$\w+\"\'\[\]\.\x{4e00}-\x{9fa5}]+)\|(\w+)([:\"\'\[\]\.\w\$\x{4e00}-\x{9fa5}]+)?).*?'.$this->TplR.'@uie',$tplFileContent,$matches); 
        $strtr  = array();		
        if ($num != false) { 
			for ($i = 0; $i < $num; $i++ ) {	
				if (function_exists($matches[3][$i])) {
					$str  = '';
					if (!empty($matches[4][$i])) {
						$str  =  implode(',',explode(':',$this->addPoint($matches[4][$i])));
					} 
					$str = $this->addPoint($matches[2][$i]).$str; 
					$_time[$i]    = '$d'.md5($matches[0][$i].time());
					$tplcode[$i]  = '<?php if ('.$this->addPoint($matches[2][$i]).') '.$_time[$i].' = '.$matches[3][$i].'('.$str.'); ?>'; 
					$strtrCode[$matches[0][$i]] = $tplcode[$i].$matches[0][$i];	
					$strtrHtml[$matches[1][$i]] = $_time[$i];
				} elseif (method_exists($this,$matches[3][$i])) {
					$str  = '';
					if (!empty($matches[4][$i])) {
						$str  =  implode(',',explode(':',$this->addPoint($matches[4][$i])));
					} 
					$str = $this->addPoint($matches[2][$i]).$str;
					$_time[$i]    = '$d'.md5($matches[0][$i].time());	
					$tplcode[$i]  = '<?php '.$_time[$i].' = $this->'.$matches[3][$i].'('.$str.'); ?>'; 
					$strtrCode[$matches[0][$i]] = $tplcode[$i].$matches[0][$i];	
					$strtrHtml[$matches[1][$i]] = $_time[$i];
				} else { 
					$strtrCode[$matches[0][$i]] = "<p style='color:red;width:100%;word-wrap:break-word;'>模版函数".$matches[3][$i]."();不能调用！</p>";
				}
			}
			if (isset($strtrCode)) {
				$tplFileContent  =  strtr( $tplFileContent,$strtrCode);		
			}
			if (isset($strtrHtml)) {
				$tplFileContent  =  strtr( $tplFileContent,$strtrHtml); 	 	
			} 
			$tplFileContent  = $this->tpl_func($tplFileContent);
		} 	
		return $tplFileContent;	 	
	}
	/**
	 * 模版层输出默认值函数
	 */
	private function _default($var = null, $_var = null) {
		if ($var) return $var; else return $_var;
	}
    /**
	 * 字符串拼接函数
	 */
	private function cat($var = '', $_var = '') {
        $str = ''; if (is_string($var)) $str .= $var;
        if (is_string($_var)) $str .= $_var; return $str;
	}
    /**
	 * 三元运算符
	 */
	private function tpl_tyor($tplFileContent){
        $matches = array();
        $num = preg_match_all('/'.$this->TplL.'(\((.+?)\)\?(.+?):([\"\'\[\]\.\w\$\x{4e00}-\x{9fa5}]+)?).*?'.$this->TplR.'/uie',$tplFileContent,$matches);
		if ($num != false) {
            $strtr      = array();
            for ($i = 0; $i < $num; $i++) {
                $parseOne    =  $this->addPoint($matches[2][$i]);
                $parseFor    =  $this->addPoint($matches[3][$i]);
                $parseFiv    =  $this->addPoint($matches[4][$i]);
				$parseFiv    =  empty($parseFiv) ? "" : $parseFiv; 
				$_time[$i]   = '$d'.md5($matches[0][$i].time());
				$tplcode[$i] = '<?php '.$_time[$i].' = ('.$parseOne.') ? '.$parseFor.':'.$parseFiv.'; ?>'; 
                $strtrCode[$matches[0][$i]] = $tplcode[$i].$matches[0][$i];	
                $strtrHtml[$matches[1][$i]] = $_time[$i];
            }
            if (isset($strtrCode)) {
				$tplFileContent  =  strtr( $tplFileContent,$strtrCode);		
			}
			if (isset($strtrHtml)) {
				$tplFileContent  =  strtr( $tplFileContent,$strtrHtml); 	 	
			}
        }	
        return $tplFileContent;
	}
	/**
	 * 生成URL
	 */
	private function tpl_cUrl($tplFileContent){
		$matches = array();
        $num = preg_match_all('/'.$this->TplL.'createUrl\s*(.*?)'.$this->TplR.'/uie',$tplFileContent,$matches); 
		if ($num != false) {   
            $strtr =   array();
            for ($i = 0; $i < $num; $i++ ) {
				$url = explode(' ', $this->addPoint($matches[1][$i]));
				$url[1] = isset($url[1]) ? 	$url[1] : null;  $url[2] = isset($url[2]) ? 	$url[2] : null;		
                $strtr[$matches[0][$i]] = '<?php echo $this->createUrl("'.$url[0].'","'.$url[1].'","'.$url[2].'"); ?>';
            }
            $tplFileContent = strtr( $tplFileContent,$strtr);
        }
        return $tplFileContent;
	}
	/**
	 * 计算URL
	 */
	private function createUrl($url, $seo = null, $exf = null) {
		if ($this->isRewrite) {
			if (empty($seo)) {
				$url = explode('?',$url);
				$url = end($url);
				if (strripos($url ,'&') !== false) {
					parse_str($url,$query);
					$return = '/';
					if (isset($query['ap'])) {
						$return .= $query['ap'].'/';	
						unset($query['ap']);
					} else {
						$return .= 'index/';	
					}
					if (isset($query['op'])) {
						$return .= $query['op'].'/';	
						unset($query['op']);
					} else {
						$return .= 'index/';
					}
					foreach ($query as $k => $v) {
						if ($v)
						$return .= $k .'/'.$v.'/';
					}
					if (empty($exf)) {
						$return .= substr(md5($url),-10).'.'.$this->Suffix;
					} else {
						$return .= $exf;
					}
				} else {
					$return = '/';
				}
			} else {
				$return = $seo;
			}
		} else {
			$return = $url;
		}
		return $return;
	} 
	/**
	 * 字符串截取
	 */
	private function _substr($str, $num = 24, $spare = '...', $sub = null){
		$return = '';
		$sub    = empty($sub) ? $num : $sub;
		if (is_string($str)) {
			if (strlen($str) > $num) {
				$return = substr($str, 0, $sub);
				$return .= $spare;
			} else {
				$return = $str;
			}
		}
		return $return;
	}
	/**
	 * 注释函数
	 */
	private function tpl_notes($tplFileContent) {
		$matches = array();
        $num = preg_match_all('/'.$this->TplL.'\*[\s\S]*?\*'.$this->TplR.'/ie',$tplFileContent,$matches); 
        $strtr  = array();
        if ($num != false) {
			for ($i = 0; $i < $num; $i++ ) {	
                $strtr[$matches[0][$i]] = '';
            }
			 $tplFileContent    =   strtr( $tplFileContent,$strtr);
		}	 
		return  $tplFileContent;		
	}
}
/**
 * 数据库驱动类	框架M层
 * @author 武恒 <8000km.cn>
 * @param  array  初始化配置数组
 */
class Db  extends Tpl
{
    private $prepareSql;
    /**
     *初始化库配置
     */
    public function realy($config) {  
        if (empty($config) || !is_array($config)){
            throw new Exception("配置错误！",202);
        }
        foreach ($config as $k => $v) {
            $this->$k = $v;
        }
    }
    /**
     * 取表名
     * @param string  表名
     * @return string 带前缀表名
     */
    public function getTableName($tableName = null) {   
            return $this->checkKey($this->dataBase['tablePrefix'].$tableName);
    }
    /**
     * 切库
     * @param string $dataBase 库表示别名
     * @return void
     */
    public function useDataBase($dataBase = null) {
        if ($dataBase != null && isset($this->dataBase) && $this->dataBase == $dataBase) {
            return 0;
        }
        $this->closeLink(); 
        if ($dataBase == null){
            reset($this->dataBases);
            $this->dataBase = current($this->dataBases);
            return 1;
        }
        if (isset($this->dataBases[$dataBase]) && is_array($this->dataBases[$dataBase])) {
            $this->dataBase = $this->dataBases[$dataBase];
            return 2;
        } else {
            throw new Exception('切库失败 数据库'.$dataBase.'不存在',202);
        }
    }
	/**
	 * 关闭当前库连接
	 * @return void
	 */
    public function closeLink() {
        if (empty($this->dataBase['dataType'])) {
            return;
        }
            switch($this->dataBase['dataType']) {
                case 'mysql':
                    if (isset($this->link) && is_resource($this->link)) {
                        mysql_close($this->link);
                        unset($this->link);
                    }
                    break;
                case 'mysqli':  
                    if (isset($this->odb) && is_object($this->odb)) {
                    if (isset($this->stmt)) {
                        $this->stmt->close();
                        unset($this->stmt);
                    }
                    $this->odb->close();
                    unset($this->odb);
                    }
                    break;
                case 'pdo':
                    if (isset($this->pdo) && is_object($this->pdo)) {
                        if (isset($this->stmt)) {
                            $this->stmt->closeCursor();
                            unset($this->stmt);
                        }
                        $this->pdo = null;
                        unset($this->pdo);
                    }
                break;
                default:
                break;
        }
    }
	/**
	 * 获取SQL 查询语句
	 * @param  string $tableName            表名
	 * @param  array or string $where		where条件
	 * @param  string $column	            查询内容
     * @param  array  $other     其他条件 键名键值 join order group limit having
	 * @return string			 返回SQL语句
	 */
    public function select($tableName = '', $column = '*', $where = '', $other = array()) {
        if (!$this->checkSql($column) || empty($tableName)) {
            return false;
        }   
        $as = ''; 
        if ((($name  = explode('as',$tableName)) && isset($name[1])) ||
			(($name  = explode('AS',$tableName)) && isset($name[1]))) { 
            $tableName = $this->dataBase['tablePrefix'] . rtrim($name[0]);
            $as        = ' AS '.$name[1];  
        } else {
            $tableName = $this->dataBase['tablePrefix'].$tableName;
        }	
        $sql    = 'SELECT ' . $column . ' FROM ' . $this->checkKey($tableName) . $as; 
        if (!empty($other)) {
            if (isset($other['join']) && is_array($other['join'])) {
                foreach ($other['join'] as $v) {
                     $sql .= ' '.$v;
                }
            } elseif (isset($other['join'])) {
                $sql .= ' '.$other['join'];
            }   
        }
        if (!empty($where)) {
                $sql .= $this->Where($where); 
        }
        if (!empty($other)) {
            if (isset($other['group'])) {
                    $sql .= ' GROUP BY ' . $other['group'];
            }
            if (isset($other['having'])) {
                    $sql .= ' HAVING ' . $other['having'];
            }
            if (isset($other['order'])) {
                    $sql .= ' ORDER BY ' . $other['order'];
            }
            if (isset($other['limit'])) {
                    $sql .= ' LIMIT ' . $other['limit'];
            }
        }
        return trim($sql,' ');
    }
    /**
     * 获得where语句
     * @param   array 
     * @return  string
     */
    public function where($where) {   
        if (empty($where)) {
            return '';
        } 
        return ' WHERE '.$where;
    }
    /**
     * 插入语句  dataArr可以是多维数组 一次插入多条数据
     * @param string $tableName  表名
     * @param array  $dataArr	 插入占位符	
     * @return string
     */
    public function insert( $tableName, $dataArr, $useName = 'INSERT INTO',$returnSql = false) {
        if (($dataArr = $this->autoVerify($tableName,$dataArr))== false) {	
            return false;
        } 
        $tableName = $this->checkKey($this->dataBase['tablePrefix'].$tableName);
        $names = $values = $sql = ''; 
        if (getMaxArr($dataArr) == 1) {
            foreach ($dataArr as $key => $v)
            {
                $names[] = $this->checkKey($key);
                if (is_null($v)) {
                    $values[] = "null";
                } else {
                    $values[] = '\'' . $v . '\'';
                }
            }   
            $sql  = ' '.$useName.' ' . $tableName . ' (' . implode(',',$names) . ') values';
            $sql .= ' (' . implode(',',$values) . ')';
        } else {		
            foreach ($dataArr as $key => $data) {
                foreach ($data as $k => $v) {
                    $names[$k] = $this->checkKey($k);
                    if (is_null($v)) {
                        $values[$key][] = "null";
                    } else {
                        $values[$key][] = '\'' . $v . '\'';
                    }
                }
            }
            $val = '';			
            foreach ( $values    as    $v) {			
                $str  = implode(',',$v);
                $val .= ' ('.$str.'),';			
            }
            $val  = trim($val, ',');
            $sql  = ' '.$useName.' ' . $tableName . ' (' . implode(',',$names) . ') values ';
            $sql .= $val;
        }  
        if ($returnSql) {
            return $sql;
        }
        return $this->query($sql,$dataArr);
    }
    /**
     * 自动验证字段
     */
     private function autoVerify($tableName,$post) {    
        if (empty($tableName) || empty($post)){
            return false;
        }
        $data = array();
        $tableInfo = $this->query($this->getTableInfo($tableName)); 
        if (getMaxArr($post) == 1) {
            foreach ($post as $k => $v) {	
                foreach ($tableInfo  as $t) {
                    if ( $k === $t["Field"] && ($v !== '' || $t["Null"] == 'YES')) {
                        $data[$k] = $v;
                        continue;
                    }
                }
            }
        } else {
            foreach ($post as $k => $v) {
                foreach ($v as $key => $val) {
                    foreach ($tableInfo  as $t) {
                        if ( $key === $t["Field"] && ($val !== '' || $t["Null"] == 'YES')) {
                            $data[$k][$key] = $val;
                        }
                    }
                }
            }
        }
        return $data;
     }
    /**
     * 获取修改数据SQL语句
     * @param string $tableName	表名  
     * @param array  $dataArr	修改的数据
     * @param string $where		条件
     * @param string $data		替换数据
     * @return string
     */
    public function update($tableName,$dataArr,$where= array(),$returnSql = false) {	
        if (empty($where) || empty($dataArr)) {
            return false;
        }   
        $tableName = $this->checkKey($this->dataBase['tablePrefix'].$tableName);
        if (is_array($dataArr)) {
            foreach ($dataArr as $key => $v) {
                if (is_null($v)) {
                    $dataList[] = $this->checkKey($key) . " = null ";   
                } else {
                    $dataList[] = $this->checkKey($key) . " = '" . $v . "'"; 
                }
            }       
            $sql = 'UPDATE ' . $tableName . ' SET ' . implode(',',$dataList). $this->Where($where);   
        } else if (is_string($dataArr)) {
            $sql = 'UPDATE ' . $tableName . ' SET ' . $dataArr . $this->Where($where);   
        }
        if ($returnSql) {
            return $sql;
        }
        return $this->query($sql);
    }
    /**
     * 获取删除语句
     * @param string $tableName 表名
     * @param string $where		条件
     * @return string
     */
    public function delete($tableName,$where = '',$returnSql = false) {
        if (empty($where)) {
            return false;
        }
        $tableName = $this->checkKey($this->dataBase['tablePrefix'].$tableName);
        $sql = 'DELETE FROM ' . $tableName . ' ' . $this->Where($where); 
        if ($returnSql) {
            return $sql;
        }
        return $this->query($sql);
    }
    /**
     * 获得Replace语句	插入或者修改语句	此函数可能只在Mysql数据库可用	慎用
     * @param string $tableName	表名
     * @param array $dataArr		插入的数据
     * @return string
     */
    public function getReplace($tableName,$dataArr) {
        return $this -> Insert($tableName,$dataArr,'REPLACE INTO');
    } 
    /**
     * 取表字段信息
     * @param string $tableName 表名
     * @return string
     */
    public function getTableInfo($tableName) {  
        if (!empty($this->dataBase['tablePrefix']) && strpos($tableName,$this->dataBase['tablePrefix']) === false) {   
            $tableName = $this->checkKey($this->dataBase['tablePrefix'].$tableName);    
        } else {
            $tableName = $this->checkKey($tableName);    
        }      
        return 'SHOW COLUMNS FROM '.$tableName;
    }
    /**
     * 执行SQL语句
     * @param string $sql  sql语句
     * @param string $data 替换数据
     * @return array
     */
    public function execute($sql = '', $data = array()) {   
        if ($sql === '' && empty($this->prepareSql)){
            return false;
        }
        $db = $this->getDB();
        switch(strtolower($this->dataBase['dataType'])) {
            case 'mysql':
                $res = $this -> DriveMysql($sql, (array) $data);
                break;
            case 'mysqli':   
                $res =  $this -> DriveMysqli($sql, (array) $data);
                break;
            case 'pdo':
                $res = $this -> DrivePdo($sql, (array) $data);
                break;
                default:
                    throw new Exception('未知数据库,库类型是:'.$this->dataBase['dataType'],202);
        }
        return $res;
    }
    /**
     * 执行SQL语句
     * @param string $sql sql语句
     * @return array  
     */
    public function query($sql = '') {
        if($sql === ''){
            return false;
        }
        $time = microtime(TRUE);
        $db = $this->getDB();   
        $this->sqlFlag = strtoupper(substr(ltrim($sql),0,1));
        switch(strtolower($this->dataBase['dataType'])) {
            case'mysqli': 
                if (($res = $db->query($sql)) === false) {
                    throw new Exception('mysqli 语句执行失败:'.$sql,202);
                } else {
                    $data = $this->getResult($res);
                }
                break;
            case'mysql':       
                if (($res = mysql_query ($sql, $db)) === false) {
                    throw new Exception('mysql 语句执行失败:'.$sql,202);
                } else {
                    $data = $this->getResult($res);
                }
                break;
            case'pdo':
                $res = $db->prepare($sql);
                $r = $res->execute();
                $error = $res->errorInfo();
                if(isset($error[2]) && $error[2] !== null) {
                    throw new Exception('PDO 语句执行失败:'.$error[2],202);
                }
                $data = $this->getResult($res, $r);
                break;
            default:
                throw new Exception('为识别的数据库资源:'.strtolower($this->dataBase['dataType']),202);
                break;
        }
        $time = ( microtime(TRUE) - $time);    
        if ($this -> SQLslow && $time > $this -> SQLtime) {
            $this -> writeLog('SQL慢语句 ：'.$sql.'执行时间：'.$time,1);
        }
        return $data;
    }
    /**
     *数据库字段过滤
     */
    public function  fdb($data) {
        if(empty($data)){
            return null;
        }
        $db = $this->getDB();  
        switch(strtolower($this->dataBase['dataType'])) {
            case'mysqli':  
                if (is_array($data)) {
                    foreach ($data as $k => $v) {
                       $data[$k] = $this->fdb($v); 
                    } 
                } else {
                    $data = $db->real_escape_string($data);       
                }
                break;
            case'mysql': 
                if (is_array($data)) {
                    foreach ($data as $k => $v) {
                       $data[$k] = $this->fdb($v); 
                    }
                } else {
                    $data = mysql_real_escape_string($data, $db);     
                }
                break;
            case'pdo':
                if (is_array($data)) {
                    foreach ($data as $k => $v) {
                       $data[$k] = $this->fdb($v); 
                    }
                } else {
                    $data = addslashes($data);
                }
                break;
            default:
                throw new Exception('为识别的数据库资源:'.strtolower($this->dataBase['dataType']),202);
                break;
        }
        return $data;
    }
    /**
     *取sql结果集
     */
    private function getResult($result, $r = null) {
        if (empty($result)) {
            return false;
        }     
        switch(strtolower($this->dataBase['dataType'])) {
            case 'mysql':
                if (is_resource($result)) {
                    $last = array();
                    while(($row  = mysql_fetch_assoc($result)) !== false) {
                        $last[] = $row;
                    }
                } else if($this->sqlFlag === 'I' || $this->sqlFlag === 'R') {
                    $result   = mysql_query('select LAST_INSERT_ID()');
                    $result   = mysql_fetch_assoc($result);
                    $last  = $result["LAST_INSERT_ID()"];
                } else if($this->sqlFlag === 'U' || $this->sqlFlag === 'D') {
                    $last  = mysql_affected_rows();
                } else {
                    $last  = $result;
                }
                break;
            case 'mysqli':
                if (is_object($result)){
                    $last = array();
                    while(($row = $result -> fetch_assoc()) !== NULL) {
                        $last[] = $row;
                    }
                } else if($this->sqlFlag === 'I' || $this->sqlFlag === 'R') {
                    $last  = $this->odb->insert_id;
                } else if($this->sqlFlag === 'U' || $this->sqlFlag === 'D') {
                    $last  = $this->odb->affected_rows;
                } else {
                    $last  = $result;
                }
                break;
            case 'pdo':
                if($this->sqlFlag === 'S'){
                    $last  = $result->fetchAll(PDO::FETCH_ASSOC);   
                } else if($this->sqlFlag === 'I' || $this->sqlFlag === 'R') {
                    $last  = (int)$this->pdo->lastInsertId();
                } else if($this->sqlFlag === 'U' || $this->sqlFlag === 'D') {
                    $last  = $result-> rowCount();
                } else {
                    $last  = $r;
                }
                break;
            default:
                throw new Exception('未知数据库,库类型为：'.$this->dataBase['dataType'],202);
        }
        return  $this->getArrOne($last);
    }
    /**
     * 开始事物管理
     * @return bool
     */
    public function begin() {
        $db = $this->getDB();
        switch(strtolower($this->dataBase['dataType'])) {
            case 'mysql':
                mysql_query('SET AUTOCOMMIT=0', $db);
                $res = mysql_query('BEGIN', $db);
                break;
            case 'mysqli':
                $res = $db->autocommit(FALSE);
                break;
            case 'pdo':
                $res = $db->beginTransaction();
                break;
            default:
            throw new Exception('未知数据库,库类型为：'.$this->dataBase['dataType'],202);
        }
        return $res;
    }
    /**
     * 事物提交
     * @return bool
     */
    public function commit() {
        $db = $this->getDB();
        switch(strtolower($this->dataBase['dataType'])) {
            case 'mysql':
                $res = mysql_query('COMMIT', $db);
                break;
            case 'mysqli':
                $res = $db->commit();
                break;
            case 'pdo':
                $res = $db->commit();
                break;
            default:
            throw new Exception('未知数据库,库类型为：'.$this->dataBase['dataType'],202);
        }
        return $res;
    }
    /**
     * 事物回滚
     * @return bool
     */
    public function rollback() {
        $db = $this->getDB();
        switch(strtolower($this->dataBase['dataType'])) {
            case 'mysql':
                $res = mysql_query('ROOLBACK', $db);
                break;
            case 'mysqli':
                $res = $db->rollback();
                break;
            case 'pdo':
                $res = $db->rollBack();
                break;
            default:
            throw new Exception('未知数据库,库类型为：'.$this->dataBase['dataType'],202);
        }
        return $res;
    }
    /**
     * Mysql 驱动
     */
    private function DriveMysql($sql, $data) {	
        if (empty($sql)){
            return false;
        }
        $time = microtime(TRUE);
        $this->sqlFlag   = strtoupper(substr(ltrim($sql),0,1));
        $num             = substr_count($sql, '?');
        if (count($data) != $num) {
            throw new Exception('预处理参数不一致，预处理参数为'.$num.'个',202);
        }
        $db   = $this->getDB();
        if (!empty($data)) {
            $datas = array();
            foreach ($data as  $v) {
                $datas[] = mysql_real_escape_string($v, $db);
            }
        }
        $i = 0;
        while (($index = strpos($sql,'?')) !== false) {  
            $sql = substr_replace($sql,'\''.$datas[$i++].'\'',$index,1);
        }  
        if ((!$res  =  mysql_query ( $sql, $db))) {
            throw new Exception('SQL语句执行失败，sql语句为:'.$sql,202);
        }
        $time = ( microtime(TRUE) - $time);  
        if ($this -> SQLslow && $time > $this -> SQLtime) {
            $this -> writeLog('SQL慢语句 ：'.$sql.'执行时间：'.$time,1);
        }		
        return $this->getResult($res);
    }
    /**
     * 引用传值
     */
    function refValues($arr) {  
        if (version_compare(PHP_VERSION, '5.3.0') >= 0) {  
            $refs = array();  
            foreach ($arr as $key => $value) { 
                $refs[$key] = &$arr[$key];  
            }
            return $refs;  
        }  
        return $arr;  
    }
    /**
     * 取数据库对象
     * @return obj
     */
     private function getDB() {
        //选取数据库类型
        switch (strtolower($this->dataBase['dataType'])) {
            case 'mysql':
                if (empty($this ->link)) {
                    if(!function_exists('mysql_connect')) {
                        throw new Exception('mysql插件未开启',202);
                    }
                    $this->link = @mysql_connect( $this->dataBase['dataUrl'].':'.$this->dataBase['port'], $this->dataBase['dataUser'], $this->dataBase['dataPwd']);
                    if (!$this->link) {
                        throw new Exception('数据库连接失败，当前连接库为：'.$this->dataBase['dataUrl'],202);
                    }
                    mysql_set_charset($this->dataBase['char']);
                    if ( !mysql_select_db($this->dataBase['name'],$this->link)) {
                        throw new Exception('数据库选择失败，数据库为:'.$this->dataBase['name'],202);
                    }
                }  
                return $this->link;
                break;
            case 'mysqli':
                if (empty($this -> odb)) {				
                    if(!class_exists('mysqli')) {
                        throw new Exception('mysqli插件未开启',202);
                    }
                    $this->odb = @new mysqli($this->dataBase['dataUrl'], $this->dataBase['dataUser'], $this->dataBase['dataPwd'], $this->dataBase['name'], (int)$this->dataBase['port']);
                    if ($this->odb -> connect_errno != 0) {
                        throw new Exception('数据库连接失败，地址是：'.$this->dataBase['dataUrl'],202);
                    }
                    $this->odb -> set_charset($this->dataBase['char']);
                }
                return $this -> odb;
                break;
            case 'pdo':
                if (empty($this -> pdo)) {		
                    if (!class_exists('PDO')) { 
                            throw new Exception('PDO工具未安装',202);
                    }
                    $dsn = 'mysql:host='.$this->dataBase['dataUrl'].';port='.(int)$this->dataBase['port'].';dbname='.$this->dataBase['name'].';charset='.$this->dataBase['char'].';';
                    try{
						$this->pdo = @new PDO($dsn, $this->dataBase['dataUser'], $this->dataBase['dataPwd']);
				    }catch(PDOException $e) { 	
					    if (2002 == $e->getCode()) {
						    throw new Exception('PDO连接数据库失败 地址是：'.$this->dataBase['dataUrl'],202);
					    } else {
						    throw new Exception('PDO工具不被支持',202);
					    }
				    }
                   $dbChar = array(
                       'SET character_set_connection='.$this->dataBase['char'],
                       'SET character_set_results='.$this->dataBase['char'],
                       'SET character_set_client=binary'
                   );
                   foreach ( $dbChar as $v) {
                       $this->pdo->exec($v);
                   } 
                   if ($this->CloseError) {
                       $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
                   } else {
                       $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
                   }
                }           
                return $this -> pdo;
                break;
            default:
                throw new Exception('未知数据库,库类型为：'.$this->dataBase['dataType'],202);
                break;
       }   
    }
    /**
     * mysqli 驱动
     */
    private function DriveMysqli($sql, $data) {     
        $time = microtime(TRUE);
        $db   = $this->getDB();         
        $this->sqlFlag = strtoupper(substr(ltrim($sql),0,1));
        //预处理
        $num      = substr_count($sql, '?');
        if ($sql != null && count($data) != $num) {
            throw new Exception('预处理参数不一致，预处理参数为'.$num.'个',202);
        }
        if ($this->prepareSql != $sql && !empty($sql)) {  
            $this->prepareSql = $sql;
            if (isset($this->stmt) && is_object($this->stmt)) {
                $this->stmt->close(); 
            }   
            if (($this->stmt = $db->prepare($sql)) == false) {
                throw new Exception('SQL语句预处理失败,错误信息是：'.$db->error.'语句是：'.$sql,202);
            }
        }
        $dataExt     = '';
        $dataList    = array();  
        if (!empty($data)) {
            foreach ($data as  $v) {
                $v = $db->real_escape_string($v);
                $dataExt    .= 's';
                $dataList[]  = $v;
            }
        }
        
        if (!empty($dataList)) {  
            array_unshift($dataList, $dataExt);	  
            call_user_func_array(array($this->stmt,'bind_param'), $this->refValues($dataList));
        }
         
        $dataList  = array();
        $dataExt   = '';
        if (($res  = $this->stmt->execute()) == false) {
            throw new Exception('SQL语句提交失败,错误信息是：'.$this->stmt->error.' 参数是：'. implode('-',$dataList),202);
        }
        if ($this->sqlFlag === 'S') {  
            $rows = array();
            $this->stmt_bind_assoc($this->stmt, $rows);
        } else if ($this->sqlFlag === 'U' || $this->sqlFlag === 'D') {
            $reset= $this->stmt->affected_rows;
        } else if ($this->sqlFlag === 'I') {
            $reset= $this->stmt->insert_id;  
        } else {
            $reset= $res;
        }

        $time = ( microtime(TRUE) - $time);    
        if ($this -> SQLslow && $time > $this -> SQLtime) {
            $this -> writeLog('SQL慢语句 ：'.$sql.'执行时间：'.$time,1);
        }

        if ($res === true && $this->sqlFlag === 'S') {
            $last = array();
            $num  = 0;  
            while($this->stmt->fetch())
            {   
                if (empty($last)) {
                        $last   = $rows;
                } else if($num  === 0) {    
                    $temp       = $last;
                    $last       = array();
                    $last[$num++] = $temp;
                    $last[$num]   = $rows;
                    $num++;
                } else {     
                    $last[$num] = $rows;
                    $num++;
                }
            }
            $this->stmt->free_result();        
            if (empty($last)) {
                $last = null;
            }
        } else if ($res === true) {
           $last = $reset; 
        }
        return $this->getArrOne($last);
    }
    /**
     * mysqli 绑定返回值
     */
    private function stmt_bind_assoc (&$stmt, &$out) {
        $data = $stmt->result_metadata();
        $fields = array();
        $out = array();

        $fields[0] = $stmt;
        $count = 1;

        while($field = mysqli_fetch_field($data)) {
            $fields[$count] = &$out[$field->name];
            $count++;
        }    
        call_user_func_array('mysqli_stmt_bind_result', $fields);
    }
    /**
     * pdo 驱动
     */
     private function DrivePdo($sql, $data) {	
        $time = microtime(TRUE);
        $db   = $this->getDB();
        $this->sqlFlag = strtoupper(substr(ltrim($sql),0,1));
        //预处理
        $num      = substr_count($sql, '?');
        if ($sql != null && count($data) != $num) {
            throw new Exception('预处理参数不一致，预处理参数为'.$num.'个',202);
        }
        if ( !empty($sql) && $this->prepareSql != $sql) {   
            $this->prepareSql = $sql;   
            if (isset($this->stmt) && is_object($this->stmt)) {
                $this->stmt->closeCursor();
            }       
            if (($this->stmt = $db->prepare($sql)) == false) {
                throw new Exception('SQL语句预处理失败,错误信息是：'.$db->error.'语句是：'.$sql,202);
            }
        }

        if (!empty($data)) {
            foreach ($data as  $v) {    
                $dataList[]    = addslashes($v);
            }   
            $r = $this->stmt -> execute($dataList);
        } else {
            $r = $this->stmt -> execute();
        }
        $time = ( microtime(TRUE) - $time);    
        if ($this -> SQLslow && $time > $this -> SQLtime) {
            $this -> writeLog('SQL慢语句 ：'.$sql.'执行时间：'.$time,1);
        }
        $error = $this->stmt->errorInfo();
        if ($error[2] !== null) {
            throw new Exception('PDO 语句执行失败:'.$error[2],202);
        }
        if ($this->sqlFlag === 'S') {
            $last  = $this->stmt->fetchAll(PDO::FETCH_ASSOC);
        } else if ($this->sqlFlag === 'I' || $this->sqlFlag === 'R') { 
            $last  = (int)$db -> lastInsertId();
        } else if ($this->sqlFlag === 'U' || $this->sqlFlag === 'D') {
            $last  = $this->stmt-> rowCount();
        } else {
            $last  = $r;
        }
        return $this->getArrOne($last);
    }
    /**
     * 整理数据
     */
     private function getArrOne($data){ 
        if (getMaxArr($data) > 1 && count($data) == 1) {
                $data = end($data);
         } 
        return $data;
     }
    /**
     * SQL 语句安全检查
     */
    private function checkSql(){
        $datas = func_get_args();
        if (empty($datas)) {
            return true;
        }
        sort($datas);
        for ($i=0;$i<count($datas);$i++) {
            if (preg_match($this->CheckSql, $datas[$i])) {
                return false;
            }
        } 
        return true;
    }
    /**
     * SQL 特殊字符转义
     */
    private function checkKey($key) {	
        if (is_array($key)) {
            $arr = array();
            foreach ($key as $k) {
                if ($offset = strrpos($k, '.')) {
                    $arr[]  = substr($k, 0, $offset).'.`'.substr($k, ($offset+1)).'`';
                } else {
                    $arr[]  = '`'.$k.'`';
                }
            }
        } else {
            if ($offset = strrpos($key, '.')) {
                 $arr   = substr($key, 0, $offset).'.`'.substr($key, ($offset+1)).'`';
            } else {
                 $arr   = '`'.$key.'`';
            }
        }
        return $arr;
    }
    /**
     *记录日志
     */
    protected function writeLog( $content = '', $level = 4) {	
        if ($this->LogLevel < $level) {
            return false;
        }
        $content = empty($content)?'调用了日志写入，但没有传入内容': $content;
        $file    = $this->Logs.Date('Y').'/'.Date('m').'/'.SIGN.'Logs'.Date('Y-m-d').'.txt';
        if (!is_file($file)) {
            new MakeFile($file);
        }
        if (is_writable($file)) {    
            $LogFile = fopen($file,'a'); 	            
            $text    = date("Y-m-d H:i:s")."\t".$content."。\r\n";								
            fwrite($LogFile,$text);		
            fclose($LogFile);
        }
    }
    /**
     * 文件缓存数据驱动
     * @param string $Group 缓存分组
     * @param int $Order 缓存文件夹深度
     */
    protected function FileCache ($Group = '', $Order = 0) {
        $Order   == 0  ? $Order = $this->AppCacheSize   : '';
        $Group   == '' ? $Group = $this->AppDataCatalog : '';
        return  new FileCache($Group, $Order, $this->Expire, $this->AppCache);
    }        
}
/**
 * 异常处理类
 * @author 武恒 <8000km.cn>
 * @param string $message 错误内容
 * @param int $code 错误代码
 */
class E extends Base
{
    // 按错误代码处理不同错误
    public function __construct ( $message, $code = 0) {	
        parent::__construct(SIGN);
        if($this->WriteLog) {
            switch($code) {
				case 202:
                    $this->writeLog($message, 1);
                break;
                case 303:
                    $this->writeLog($message, 1);
                break;
				case 404:
                    $this->writeLog($message, 2);
                break;
                case 505:
                    $this->writeLog($message.'-详细信息-'.'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'], 1);
                break;
                default:
                break;
            }
        }
        if (!$this->CloseError) {
            echo $message;
        } else {
            $this->setStatus(404);
        }
    }
}
/**
 * 文件路径生成类
 * @author 武恒	<网址8000km.cn>
 * @param string $dir 生成的路径
 */
class MakeDir {
    private $temp,$dir;
    public  $info;
    public function __construct($dir = '') {
        if ($dir == '') {
            return;
        }
        $this->dir($dir);
    }
    /**
     * 检查参数
     * @param string $dir 路径
     * @return bool
     */
    public function dir($dir) { 
        if (is_dir($dir)) {
            $this ->info = '文件夹已存在';
            return true;
        }
        if (is_file($dir)) {
            throw new Exception('创建目录失败,存在同名文件',303);	
        }
        $f    = substr($dir,0,1);
        if($f == '.' ) {
            $dir = dirname(__FILE__).substr($dir,1);
        } else if ($f == '\\'){
            $dir = dirname(__FILE__).$dir;
        } else if ($f == '/'){
            $dir;
        } else if (substr($dir,1,1) != ':') {
            $dir = dirname(__FILE__).'/'.$dir;
        }
        $this -> temp = array();
        $dir = strtr( $dir, array('\\' => '/'));
        $dir = rtrim($dir,'/');
        $this -> proDir($dir);
    }
    /**
     * 生成路径
     */
    private function proDir($dir) {	
        if (!@mkdir($dir,0700,true)) {
            throw new Exception('目录'.$dir.'不可写!',303);	
        }
        $this ->info = '';
        return true;
    }
}
/**
 * 文件生成类
 * @author 武恒 <8000km.cn>
 * @param string $path 文件路径
 * @param string $text 文件内容
 */
class MakeFile
{
    public $info;
    public function __construct($path = '',$text = '') {
        if ($path == '') {
            return ;
        }
        $this->fil($path, $text);
    }
   /**
    * 检查生成文件路径和规范
    * @param string $path 路径
    * @param string $text 内容
    * @return bool
    */
    public function fil ($path = '', $text = '') {
        if ($path == '') {
            $this ->info = '空参';	
            return false;
        }
        $path = strtr( $path, array('\\' => '/'));
        if (!is_dir($dir = substr($path, 0, strripos($path,'/')))) {
             new MakeDir($dir); 
        }
        if (!is_writable($dir)) {
            throw new Exception('目录'.$dir.'不可写!',303);	
        }
        return $this -> writeText($text, $path);
    }
    /**
     * 生成文件
     */
    private function writeText($text, $path) {
        if ( @file_put_contents($path, $text, LOCK_EX) === false ) {
            $this->info = '生成文件失败'; 
            $info = false;
        } else {
            $info = true;
        }
        return $info;
    }
}
/**
 *文件缓存类
 */
class FileCache 
{	
    public function  __construct( $Group, $Order , $Expire, $AppCache) {     
        $this->Group = $Group;
        $this->Order = $Order;
        $this->Expire   = $Expire;
        $this->AppCache = $AppCache;
    }
    /**
     * 设置缓存文件
     * @param $key 缓存文件唯一识别值
     * @param $value 缓存数据
     * @param $expire 缓存时间
     * @return bool
     */
    public function set( $key, $value, $expire = 0) {
        $expire  ==  0 ? $expire      = $this->Expire : $expire;
        $value   =  (time()+$expire).serialize( $value);	
        return @file_put_contents ( $this->getFilePath( $key), $value, LOCK_EX );
    }
    /**
     * 取缓存
     * @param $key 缓存文件唯一识别值
     * @return mixed
     */
    public function get($key) {	
        if ( is_writable(($path = $this->getFilePath( $key)))) {
            $data    = file_get_contents( $path );
            $expires = substr($data, 0, 10);
            if ( $expires - time() > 0) {
                $data = substr(file_get_contents( $path ),10);
                $res  = unserialize($data);
            } else {
                unlink($path);
                $res  = false;
            }
        } else {
            $res  = false;		
        }
        return $res;
    }
    /**
     * 取文件路径
     * @param string $key 文件唯一识别值
     * @return string
     */
    public function getFilePath($key) {
        $key = md5($key); 
        $dir = $this->AppCache . $this->Group .'/';
        if ($this->Order > 0) {
            for (  $i = 0; $i < (int) $this->Order; $i++){
                $dir  = $dir. substr($key, $i*2, 2).'/';
            }
        }
        new MakeDir( $dir);		
        return $dir. $key . '.ca';
    }
    /**
     * 清空缓存文件夹
     * @return bool
     */
    public function cle() {
        return delDir($this->AppCache.$this->Group, false);
    }
    /**
     * 删除缓存文件
     * @param string $key 文件唯一识别值
     * @return bool
     */
    public function del($key = null) {
        if($key == null) {
            return false;
        }
        if (is_writable($file = $this->getFilePath($key))) {
            return unlink($file);
        } else {
            return false;
        }
    }
}